diff --git a/.github/release.yml b/.github/release.yml deleted file mode 100644 index 570c4fc0..00000000 --- a/.github/release.yml +++ /dev/null @@ -1,26 +0,0 @@ -changelog: - categories: - - title: "Breaking changes" - labels: - - "breaking change" - - title: "New features" - labels: - - "new feature" - - title: "Bug fixes" - labels: - - bug - - title: Changes - labels: - - change - - title: Deprecated - labels: - - deprecate - - title: Removed - labels: - - remove - - title: "Update Dependencies" - labels: - - dependencies - - title: Others - labels: - - "*" diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml deleted file mode 100644 index 4123d4a6..00000000 --- a/.github/workflows/gh-pages.yml +++ /dev/null @@ -1,53 +0,0 @@ -# Based on starter workflow -# https://github.com/actions/starter-workflows/blob/8217436fdee2338da2d6fd02b7c9fcff634c40e7/pages/static.yml -# -# Simple workflow for deploying static content to GitHub Pages -name: "GitHub Pages" - -on: - # Runs on pushes targeting the default branch - push: - branches: - - master - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Allow one concurrent deployment -concurrency: - group: "pages" - cancel-in-progress: true - -jobs: - # Single deploy job since we're just deploying - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - # Generate cargo-doc - - name: Generate documentation - run: cargo doc --no-deps - - - name: Setup Pages - uses: actions/configure-pages@v5 - - # Upload target/doc directory - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: 'target/doc' - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 diff --git a/.github/workflows/intel-mkl.yml b/.github/workflows/intel-mkl.yml deleted file mode 100644 index 5e348e48..00000000 --- a/.github/workflows/intel-mkl.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: intel-mkl - -on: - push: - branches: - - master - pull_request: {} - workflow_dispatch: - -jobs: - intel-mkl: - strategy: - fail-fast: false - matrix: - system: [ubuntu-22.04, windows-latest] - runs-on: ${{ matrix.system }} - steps: - - uses: actions/checkout@v4 - - name: cargo test - run: cargo test --manifest-path=ndarray-linalg/Cargo.toml --no-default-features --features=intel-mkl-static-lp64-seq --verbose diff --git a/.github/workflows/netlib.yml b/.github/workflows/netlib.yml deleted file mode 100644 index 70048503..00000000 --- a/.github/workflows/netlib.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: netlib - -on: - push: - branches: - - master - pull_request: {} - workflow_dispatch: - -jobs: - linux: - strategy: - fail-fast: false - matrix: - feature: - - static - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: apt install gfortran - run: | - sudo apt update - sudo apt install -y gfortran - - name: cargo test - run: cargo test --manifest-path=ndarray-linalg/Cargo.toml --no-default-features --features=netlib-${{ matrix.feature }} diff --git a/.github/workflows/openblas.yml b/.github/workflows/openblas.yml deleted file mode 100644 index 5375be70..00000000 --- a/.github/workflows/openblas.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: openblas - -on: - push: - branches: - - master - pull_request: {} - workflow_dispatch: - -jobs: - linux: - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - matrix: - feature: - - static - - system - steps: - - uses: actions/checkout@v4 - - name: apt install gfortran - run: | - sudo apt update - sudo apt install -y gfortran - - name: Install OpenBLAS by apt - run: | - sudo apt update - sudo apt install -y libopenblas-dev - if: ${{ contains(matrix.feature, 'system') }} - - name: cargo test - run: cargo test --manifest-path=ndarray-linalg/Cargo.toml --no-default-features --features=openblas-${{ matrix.feature }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml deleted file mode 100644 index 66ca1553..00000000 --- a/.github/workflows/rust.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Rust - -on: - push: - branches: - - master - pull_request: {} - workflow_dispatch: - -jobs: - check-format: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: fmt - run: cargo fmt -- --check - - check: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: cargo check - run: cargo check --all-targets - - check-doc: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: cargo doc - run: cargo doc --no-deps - - clippy: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: cargo clippy - run: cargo clippy - - coverage: - runs-on: ubuntu-22.04 - container: - image: xd009642/tarpaulin:develop-nightly - options: --security-opt seccomp=unconfined - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@nightly - - name: Install Cross - uses: taiki-e/install-action@v2 - with: - tool: cargo-tarpaulin - - name: Generate code coverage - run: cargo +nightly tarpaulin --features=intel-mkl-static --out xml - - name: Upload to codecov.io - uses: codecov/codecov-action@v5 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e228a4bb..00000000 --- a/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Cargo -# will have compiled files and executables -target/ -*.rustfmt -rusty-tags.* - -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -Cargo.lock - -# cargo fmt -*.bk - -# IntelliJ Rust -.idea -*.iml - -# coverage -*.xml diff --git a/.gitmodules b/.lock old mode 100644 new mode 100755 similarity index 100% rename from .gitmodules rename to .lock diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt new file mode 100644 index 00000000..34e48134 --- /dev/null +++ b/COPYRIGHT.txt @@ -0,0 +1,46 @@ +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.ttf.woff2, + SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, + SourceSerif4-It.ttf.woff2): + + Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name + 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United + States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerif4-LICENSE.md. + +This copyright file is intended to be distributed with rustdoc output. diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index ba1ae403..00000000 --- a/Cargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[workspace] -members = [ - "ndarray-linalg", - "lax", -] diff --git a/FiraSans-LICENSE.txt b/FiraSans-LICENSE.txt new file mode 100644 index 00000000..ff9afab0 --- /dev/null +++ b/FiraSans-LICENSE.txt @@ -0,0 +1,94 @@ +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/FiraSans-Medium.woff2 b/FiraSans-Medium.woff2 new file mode 100644 index 00000000..7a1e5fc5 Binary files /dev/null and b/FiraSans-Medium.woff2 differ diff --git a/FiraSans-Regular.woff2 b/FiraSans-Regular.woff2 new file mode 100644 index 00000000..e766e06c Binary files /dev/null and b/FiraSans-Regular.woff2 differ diff --git a/LICENSE-APACHE.txt b/LICENSE-APACHE.txt new file mode 100644 index 00000000..16fe87b0 --- /dev/null +++ b/LICENSE-APACHE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT.txt b/LICENSE-MIT.txt new file mode 100644 index 00000000..31aa7938 --- /dev/null +++ b/LICENSE-MIT.txt @@ -0,0 +1,23 @@ +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. diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 55150e4b..00000000 --- a/LICENSE.md +++ /dev/null @@ -1,49 +0,0 @@ -# License - -The project is dual licensed under the terms of the Apache License, Version 2.0, -and the MIT License. You may obtain copies of the two licenses at - -* https://www.apache.org/licenses/LICENSE-2.0 and -* https://opensource.org/licenses/MIT, respectively. - -The following two notices apply to every file of the project. - -## The Apache License - -``` -Copyright 2016 The ndarray-linalg Developers - -Licensed under the Apache License, Version 2.0 (the “License”); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. -``` - -## The MIT License - -``` -Copyright 2016 The ndarray-linalg 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 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. -``` diff --git a/NanumBarunGothic-LICENSE.txt b/NanumBarunGothic-LICENSE.txt new file mode 100644 index 00000000..0bf46682 --- /dev/null +++ b/NanumBarunGothic-LICENSE.txt @@ -0,0 +1,99 @@ +Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/), + +with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, +NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, +Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, +NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, +Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/NanumBarunGothic.ttf.woff2 b/NanumBarunGothic.ttf.woff2 new file mode 100644 index 00000000..1866ad4b Binary files /dev/null and b/NanumBarunGothic.ttf.woff2 differ diff --git a/README.md b/README.md deleted file mode 100644 index 85b1428c..00000000 --- a/README.md +++ /dev/null @@ -1,97 +0,0 @@ -ndarray-linalg -=============== -[![crate](https://img.shields.io/crates/v/ndarray-linalg.svg)](https://crates.io/crates/ndarray-linalg) -[![docs.rs](https://docs.rs/ndarray-linalg/badge.svg)](https://docs.rs/ndarray-linalg) -[![master](https://img.shields.io/badge/docs-master-blue)](https://rust-ndarray.github.io/ndarray-linalg/ndarray_linalg/index.html) - -Linear algebra package for Rust with [ndarray](https://github.com/rust-ndarray/ndarray) based on external LAPACK implementations. - -Examples ---------- -See [examples](https://github.com/termoshtt/ndarray-linalg/tree/master/ndarray-linalg/examples) directory. - -**Note**: To run examples, you must specify which backend will be used (as described below). -For example, you can execute the [solve](ndarray-linalg/examples/solve.rs) example with the OpenBLAS backend like this: - -```sh -cargo run --example solve --features=openblas -``` - -and run all tests of ndarray-linalg with OpenBLAS - -```sh -cargo test --features=openblas -``` - -Backend Features ------------------ - -There are three LAPACK source crates: - -- [openblas-src](https://github.com/blas-lapack-rs/openblas-src) -- [netlib-src](https://github.com/blas-lapack-rs/netlib-src) -- [intel-mkl-src](https://github.com/rust-math/rust-intel-mkl) - -`ndarray_linalg` must link **just one** of them for LAPACK FFI. - -```toml -[dependencies] -ndarray = "0.14" -ndarray-linalg = { version = "0.13", features = ["openblas-static"] } -``` - -Supported features are following: - -| Feature | Link type | Requirements | Description | -|:-----------------|:---------------|:--------------------|:-----------------------------------------------------------------------------------------------| -| openblas-static | static | gcc, gfortran, make | Build OpenBLAS in your project, and link it statically | -| openblas-system | dynamic/static | libopenblas-dev | Seek OpenBLAS in system, and link it | -| netlib-static | static | gfortran, make | Same as openblas-static except for using reference LAPACK | -| netlib-system | dynamic/static | liblapack-dev | Same as openblas-system except for using reference LAPACK | -| intel-mkl-static | static | (pkg-config) | Seek static library of Intel MKL from system, or download if not found, and link it statically | -| intel-mkl-system | dynamic | (pkg-config) | Seek shared library of Intel MKL from system, and link it dynamically | - -- You must use **just one** feature of them. -- `dynamic/static` means it depends on what is found in the system. When the system has `/usr/lib/libopenblas.so`, it will be linked dynamically, and `/usr/lib/libopenblas.a` will be linked statically. Dynamic linking is prior to static linking. -- Requirements notices: - - `gcc` and `gfortran` can be another compiler, e.g. `icc` and `ifort`. - - `libopenblas-dev` is package name in Debian, Ubuntu, and other derived distributions. - There are several binary packages of OpenBLAS, i.e. `libopenblas-{openmp,pthread,serial}-dev`. - It can be other names in other distributions, e.g. Fedora, ArchLinux, and so on. - - `pkg-config` is used for searching Intel MKL packages in system, and it is optional. See [intel-mkl-src/README.md](https://github.com/rust-math/intel-mkl-src/blob/master/README.md#how-to-find-system-mkl-libraries) for detail. - -### For library developer - -If you are creating a library depending on this crate, we encourage you not to link any backend: - -```toml -[dependencies] -ndarray = "0.13" -ndarray-linalg = "0.12" -``` - -The cargo's feature is additive. If your library (saying `lib1`) set a feature `openblas-static`, -the application using `lib1` builds ndarray_linalg with `openblas-static` feature though they want to use `intel-mkl-static` backend. - -See [the cargo reference](https://doc.rust-lang.org/cargo/reference/features.html) for detail - -Tested Environments --------------------- - -Only x86_64 system is supported currently. - -|Backend | Linux | Windows | macOS | -|:--------|:-----:|:-------:|:-----:| -|OpenBLAS |✔️ |- |- | -|Netlib |✔️ |- |- | -|Intel MKL|✔️ |✔️ |✔️ | - -License --------- - -**CAUTION** Be sure that if you use `intel-mkl-src` backend, you have to accept [Intel Simplified Software License](https://software.intel.com/content/www/us/en/develop/articles/end-user-license-agreement.html) -in addition to the MIT-License or Apache-2.0 License. - -Dual-licensed to be compatible with the Rust project. -Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 or the MIT license http://opensource.org/licenses/MIT, at your option. - diff --git a/SourceCodePro-It.ttf.woff2 b/SourceCodePro-It.ttf.woff2 new file mode 100644 index 00000000..462c34ef Binary files /dev/null and b/SourceCodePro-It.ttf.woff2 differ diff --git a/SourceCodePro-LICENSE.txt b/SourceCodePro-LICENSE.txt new file mode 100644 index 00000000..07542572 --- /dev/null +++ b/SourceCodePro-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/SourceCodePro-Regular.ttf.woff2 b/SourceCodePro-Regular.ttf.woff2 new file mode 100644 index 00000000..10b558e0 Binary files /dev/null and b/SourceCodePro-Regular.ttf.woff2 differ diff --git a/SourceCodePro-Semibold.ttf.woff2 b/SourceCodePro-Semibold.ttf.woff2 new file mode 100644 index 00000000..5ec64eef Binary files /dev/null and b/SourceCodePro-Semibold.ttf.woff2 differ diff --git a/SourceSerif4-Bold.ttf.woff2 b/SourceSerif4-Bold.ttf.woff2 new file mode 100644 index 00000000..db57d214 Binary files /dev/null and b/SourceSerif4-Bold.ttf.woff2 differ diff --git a/SourceSerif4-It.ttf.woff2 b/SourceSerif4-It.ttf.woff2 new file mode 100644 index 00000000..1cbc021a Binary files /dev/null and b/SourceSerif4-It.ttf.woff2 differ diff --git a/SourceSerif4-LICENSE.md b/SourceSerif4-LICENSE.md new file mode 100644 index 00000000..68ea1892 --- /dev/null +++ b/SourceSerif4-LICENSE.md @@ -0,0 +1,93 @@ +Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/SourceSerif4-Regular.ttf.woff2 b/SourceSerif4-Regular.ttf.woff2 new file mode 100644 index 00000000..2db73fe2 Binary files /dev/null and b/SourceSerif4-Regular.ttf.woff2 differ diff --git a/ayu.css b/ayu.css new file mode 100644 index 00000000..a9c9be0d --- /dev/null +++ b/ayu.css @@ -0,0 +1 @@ + body,#settings-menu #settings,#settings-menu #settings::before{background-color:#0f1419;color:#c5c5c5;}.setting-line .radio-line input{border-color:#c5c5c5;}.setting-line .radio-line input:checked{box-shadow:inset 0 0 0 3px #0f1419;background-color:#ffb454;}.setting-line .radio-line input:focus{box-shadow:0 0 1px 1px #ffb454;}.setting-line .radio-line input:checked:focus{box-shadow:inset 0 0 0 3px 0f1419,0 0 2px 2px #ffb454;}.setting-line .radio-line input:hover{border-color:#ffb454 !important;}.slider{background-color:#ccc;}.slider:before{background-color:white;}input:checked+.slider{background-color:#ffb454;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}h1,h2,h3,h4{color:white;}h1.fqn{border-bottom-color:#5c6773;}h1.fqn a{color:#fff;}h2,h3,h4{border-bottom-color:#5c6773;}h4{border:none;}.in-band{background-color:#0f1419;}.invisible{background:rgba(0,0,0,0);}.docblock code{color:#ffb454;}.code-header{color:#e6e1cf;}.docblock pre>code,pre>code{color:#e6e1cf;}span code{color:#e6e1cf;}.docblock a>code{color:#39AFD7 !important;}.docblock code,.docblock-short code{background-color:#191f26;}pre,.rustdoc.source .example-wrap{color:#e6e1cf;background-color:#191f26;}.sidebar,.mobile-topbar,.sidebar-menu-toggle{background-color:#14191f;}.rust-logo{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);}*{scrollbar-color:#5c6773 #24292f;}.sidebar{scrollbar-color:#5c6773 #24292f;}::-webkit-scrollbar-track{background-color:transparent;}::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar::-webkit-scrollbar-track{background-color:transparent;}.sidebar::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar .current,.sidebar a:hover{background-color:transparent;color:#ffb44c;}.source .sidebar{background-color:#14191f;}.sidebar-elems .location{color:#ff7733;}.line-numbers span{color:#5c6773;}.line-numbers .line-highlighted{color:#708090;background-color:rgba(255,236,164,0.06);padding-right:4px;border-right:1px solid #ffb44c;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5,.docblock h6{border-bottom-color:#5c6773;}.docblock table td,.docblock table th{border-color:#5c6773;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#c5c5c5;}.search-results a:hover{background-color:#777;}.search-results a:focus{color:#000 !important;background-color:#c6afb3;}.search-results a{color:#0096cf;}.search-results a div.desc{color:#c5c5c5;}.content .item-info::before{color:#ccc;}.content span.foreigntype,.content a.foreigntype{color:#ffa0a5;}.content span.union,.content a.union{color:#ffa0a5;}.content span.constant,.content a.constant,.content span.static,.content a.static{color:#39AFD7;}.content span.primitive,.content a.primitive{color:#ffa0a5;}.content span.traitalias,.content a.traitalias{color:#39AFD7;}.content span.keyword,.content a.keyword{color:#39AFD7;}.content span.externcrate,.content span.mod,.content a.mod{color:#39AFD7;}.content span.struct,.content a.struct{color:#ffa0a5;}.content span.enum,.content a.enum{color:#ffa0a5;}.content span.trait,.content a.trait{color:#39AFD7;}.content span.type,.content a.type{color:#39AFD7;}.content span.type,.content a.type,.block a.current.type{color:#39AFD7;}.content span.associatedtype,.content a.associatedtype,.block a.current.associatedtype{color:#39AFD7;}.content span.fn,.content a.fn,.content span.method,.content a.method,.content span.tymethod,.content a.tymethod,.content .fnname{color:#fdd687;}.content span.attr,.content a.attr,.content span.derive,.content a.derive,.content span.macro,.content a.macro{color:#a37acc;}.sidebar a{color:#53b1db;}.sidebar a.current.type{color:#53b1db;}.sidebar a.current.associatedtype{color:#53b1db;}pre.rust .comment{color:#788797;}pre.rust .doccomment{color:#a1ac88;}nav.main .current{border-top-color:#5c6773;border-bottom-color:#5c6773;}nav.main .separator{border:1px solid #5c6773;}a{color:#39AFD7;}a#toggle-all-docs,a.anchor,.small-section-header a,#source-sidebar a,pre.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,.in-band a{color:#c5c5c5;}.sidebar h2 a,.sidebar h3 a{color:white;}.search-results a{color:#0096cf;}body.source .example-wrap pre.rust a{background:#333;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}details.rustdoc-toggle>summary::before,details.undocumented>summary::before{filter:invert(100%);}#crate-search,.search-input{background-color:#141920;border-color:#424c57 !important;}.search-input{color:#ffffff;}.module-item .stab,.import-item .stab{color:#000;}.stab.empty-impl{}.stab.unstable,.stab.deprecated,.stab.portability,.stab.empty-impl{color:#c5c5c5;background:#314559 !important;border-style:none !important;border-radius:4px;padding:3px 6px 3px 6px;}.stab.portability>code{color:#e6e1cf;background:none;}#help>div{background:#14191f;box-shadow:0px 6px 20px 0px black;border:none;border-radius:4px;}#help span.bottom,#help span.top{border-color:#5c6773;}.rightside,.out-of-band{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:#788797;}.line-numbers :target{background-color:transparent;}pre.rust .number,pre.rust .string{color:#b8cc52;}pre.rust .kw,pre.rust .kw-2,pre.rust .prelude-ty,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .op,pre.rust .lifetime{color:#ff7733;}pre.rust .macro,pre.rust .macro-nonterminal{color:#a37acc;}pre.rust .question-mark{color:#ff9011;}pre.rust .self{color:#36a3d9;font-style:italic;}pre.rust .attribute{color:#e6e1cf;}pre.rust .attribute .ident,pre.rust .attribute .op{color:#e6e1cf;}.example-wrap>pre.line-number{color:#5c67736e;border:none;}a.test-arrow{font-size:100%;color:#788797;border-radius:4px;background-color:rgba(57,175,215,0.09);}a.test-arrow:hover{background-color:rgba(57,175,215,0.368);color:#c5c5c5;}.toggle-label,.code-attribute{color:#999;}:target{background:rgba(255,236,164,0.06);border-right:3px solid rgba(255,180,76,0.85);}pre.compile_fail{border-left:2px solid rgba(255,0,0,.4);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.4);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#39AFD7;}.tooltip::after{background-color:#314559;color:#c5c5c5;border:1px solid #5c6773;}.tooltip::before{border-color:transparent #314559 transparent transparent;}.notable-traits-tooltiptext{background-color:#314559;border-color:#5c6773;}.notable-traits-tooltiptext .notable{border-bottom-color:#5c6773;}#titles>button.selected{background-color:#141920 !important;border-bottom:1px solid #ffb44c !important;border-top:none;}#titles>button:not(.selected){background-color:transparent !important;border:none;}#titles>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}#titles>button>div.count{color:#888;}.search-input:focus{}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{}.content span.struct,.content a.struct,.block a.current.struct{}#titles>button:hover,#titles>button.selected{}.content span.typedef,.content a.typedef,.block a.current.typedef{}.content span.union,.content a.union,.block a.current.union{}pre.rust .lifetime{}.stab.unstable{}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){}.content span.enum,.content a.enum,.block a.current.enum{}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{}.content span.keyword,.content a.keyword,.block a.current.keyword{}pre.rust .comment{}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{}pre.rust .kw{}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{}pre.rust .doccomment{}.stab.deprecated{}.content a.attr,.content a.derive,.content a.macro{}.stab.portability{}.content span.primitive,.content a.primitive,.block a.current.primitive{}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{}pre.rust .kw-2,pre.rust .prelude-ty{}.content span.trait,.content a.trait,.block a.current.trait{}.search-results a:focus span{}a.result-trait:focus{}a.result-traitalias:focus{}a.result-mod:focus,a.result-externcrate:focus{}a.result-mod:focus{}a.result-externcrate:focus{}a.result-enum:focus{}a.result-struct:focus{}a.result-union:focus{}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{}a.result-type:focus{}a.result-associatedtype:focus{}a.result-foreigntype:focus{}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{}a.result-constant:focus,a.result-static:focus{}a.result-primitive:focus{}a.result-keyword:focus{}.sidebar a.current.enum{}.sidebar a.current.struct{}.sidebar a.current.foreigntype{}.sidebar a.current.attr,.sidebar a.current.derive,.sidebar a.current.macro{}.sidebar a.current.union{}.sidebar a.current.constant .sidebar a.current.static{}.sidebar a.current.primitive{}.sidebar a.current.externcrate .sidebar a.current.mod{}.sidebar a.current.trait{}.sidebar a.current.traitalias{}.sidebar a.current.fn,.sidebar a.current.method,.sidebar a.current.tymethod{}.sidebar a.current.keyword{}@media (max-width:700px){.sidebar-menu{background-color:#14191f;border-bottom-color:#5c6773;border-right-color:#5c6773;}.sidebar-elems{background-color:#14191f;border-right-color:#5c6773;}#sidebar-filler{background-color:#14191f;border-bottom-color:#5c6773;}}kbd{color:#c5c5c5;background-color:#314559;border-color:#5c6773;border-bottom-color:#5c6773;box-shadow:inset 0 -1px 0 #5c6773;}#settings-menu>a,#help-button{border-color:#5c6773;background-color:#0f1419;color:#fff;}#settings-menu>a img{filter:invert(100);}#settings-menu #settings,#settings-menu #settings::before{border-color:#5c6773;}#copy-path{color:#fff;}#copy-path>img{filter:invert(70%);}#copy-path:hover>img{filter:invert(100%);}#settings-menu>a:hover,#settings-menu>a:focus,#help-button:hover,#help-button:focus{border-color:#e0e0e0;}#theme-choices{border-color:#5c6773;background-color:#0f1419;}#theme-choices>button:not(:first-child){border-top-color:#5c6773;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:rgba(110,110,110,0.33);}.search-results .result-name span.alias{color:#c5c5c5;}.search-results .result-name span.grey{color:#999;}#sidebar-toggle{background-color:#14191f;}#sidebar-toggle:hover{background-color:rgba(70,70,70,0.33);}#source-sidebar{background-color:#14191f;}#source-sidebar>.title{color:#fff;border-bottom-color:#5c6773;}div.files>a:hover,div.name:hover{background-color:#14191f;color:#ffb44c;}div.files>.selected{background-color:#14191f;color:#ffb44c;}.scraped-example-list .scrape-help{border-color:#aaa;color:#eee;}.scraped-example-list .scrape-help:hover{border-color:white;color:white;}.more-examples-toggle summary,.more-examples-toggle .hide-more{color:#999;}.scraped-example .example-wrap .rust span.highlight{background:rgb(91,59,1);}.scraped-example .example-wrap .rust span.highlight.focus{background:rgb(124,75,15);}.scraped-example:not(.expanded) .code-wrapper:before{background:linear-gradient(to bottom,rgba(15,20,25,1),rgba(15,20,25,0));}.scraped-example:not(.expanded) .code-wrapper:after{background:linear-gradient(to top,rgba(15,20,25,1),rgba(15,20,25,0));}.toggle-line-inner{background:#999;}.toggle-line:hover .toggle-line-inner{background:#c5c5c5;} \ No newline at end of file diff --git a/clipboard.svg b/clipboard.svg new file mode 100644 index 00000000..8adbd996 --- /dev/null +++ b/clipboard.svg @@ -0,0 +1 @@ + diff --git a/crates.js b/crates.js new file mode 100644 index 00000000..55d1c2a6 --- /dev/null +++ b/crates.js @@ -0,0 +1 @@ +window.ALL_CRATES = ["lax","ndarray_linalg"]; \ No newline at end of file diff --git a/dark.css b/dark.css new file mode 100644 index 00000000..d8bd2002 --- /dev/null +++ b/dark.css @@ -0,0 +1 @@ +body,#settings-menu #settings,#settings-menu #settings::before{background-color:#353535;color:#ddd;}.setting-line .radio-line input{border-color:#ddd;}.setting-line .radio-line input:checked{box-shadow:inset 0 0 0 3px #353535;background-color:#2196f3;}.setting-line .radio-line input:focus{box-shadow:0 0 1px 1px #2196f3;}.setting-line .radio-line input:checked:focus{box-shadow:inset 0 0 0 3px #353535,0 0 2px 2px #2196f3;}.setting-line .radio-line input:hover{border-color:#2196f3 !important;}.slider{background-color:#ccc;}.slider:before{background-color:white;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}h1,h2,h3,h4{color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3,h4{border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre,.rustdoc.source .example-wrap{background-color:#2A2A2A;}.sidebar,.mobile-topbar,.sidebar-menu-toggle{background-color:#505050;}.rust-logo{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff)}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) #5a5a5a;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current,.sidebar a:hover{background:#444;}.source .sidebar{background-color:#565656;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5,.docblock h6{border-bottom-color:#DDD;}.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.search-results a:hover{background-color:#777;}.search-results a:focus{color:#eee !important;background-color:#616161;}.search-results a:focus span{color:#eee !important;}a.result-trait:focus{background-color:#013191;}a.result-traitalias:focus{background-color:#013191;}a.result-mod:focus,a.result-externcrate:focus{background-color:#884719;}a.result-enum:focus{background-color:#194e9f;}a.result-struct:focus{background-color:#194e9f;}a.result-union:focus{background-color:#194e9f;}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{background-color:#4950ed;}a.result-type:focus{background-color:#194e9f;}a.result-associatedtype:focus{background-color:#884719;}a.result-foreigntype:focus{background-color:#194e9f;}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{background-color:#217d1c;}a.result-constant:focus,a.result-static:focus{background-color:#884719;}a.result-primitive:focus{background-color:#194e9f;}a.result-keyword:focus{background-color:#884719;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#2dbfb8;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#2dbfb8;}.content span.associatedtype,.content a.associatedtype,.block a.current.associatedtype{color:#D2991D;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#2dbfb8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#2dbfb8;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#D2991D;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2dbfb8;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#D2991D;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b78cf2;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#D2991D;}.sidebar a{color:#fdbf35;}.sidebar a.current.enum{color:#12ece2;}.sidebar a.current.struct{color:#12ece2;}.sidebar a.current.type{color:#12ece2;}.sidebar a.current.associatedtype{color:#fdbf35;}.sidebar a.current.foreigntype{color:#12ece2;}.sidebar a.current.attr,.sidebar a.current.derive,.sidebar a.current.macro{color:#0be900;}.sidebar a.current.union{color:#12ece2;}.sidebar a.current.constant .sidebar a.current.static{color:#fdbf35;}.sidebar a.current.primitive{color:#12ece2;}.sidebar a.current.externcrate .sidebar a.current.mod{color:#fdbf35;}.sidebar a.current.trait{color:#cca7ff;}.sidebar a.current.traitalias{color:#cca7ff;}.sidebar a.current.fn,.sidebar a.current.method,.sidebar a.current.tymethod{color:#32d479;}.sidebar a.current.keyword{color:#fdbf35;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#D2991D;}a#toggle-all-docs,a.anchor,.small-section-header a,#source-sidebar a,pre.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,.in-band a{color:#ddd;}.search-results a{color:#ddd;}a.test-arrow{color:#dedede;}body.source .example-wrap pre.rust a{background:#333;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}details.rustdoc-toggle>summary::before,details.undocumented>summary::before{filter:invert(100%);}#crate-search,.search-input{color:#111;background-color:#f0f0f0;border-color:#f0f0f0 !important;}.search-input{border-color:#e0e0e0;}.search-input:focus{border-color:#008dfd;}.module-item .stab,.import-item .stab{color:#ddd;}.stab.empty-impl{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.deprecated{background:#ffc4c4;border-color:#db7b7b;color:#2f2f2f;}.stab.portability{background:#F3DFFF;border-color:#b07bdb;color:#2f2f2f;}.stab.portability>code{background:none;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help span.bottom,#help span.top{border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);}.rightside,.out-of-band{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label,.code-attribute{color:#999;}:target{background-color:#494a3d;border-right:3px solid #bb7410;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip::after{background-color:#000;color:#fff;border-color:#000;}.tooltip::before{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#111;border-color:#777;}.notable-traits-tooltiptext .notable{border-bottom-color:#d2d2d2;}#titles>button:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>button:hover,#titles>button.selected{border-top-color:#0089ff;background-color:#353535;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow:inset 0 -1px 0 #c6cbd1;}#settings-menu>a,#help-button{border-color:#e0e0e0;background:#f0f0f0;color:#000;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button:hover,#help-button:focus{border-color:#ffb900;}#settings-menu #settings,#settings-menu #settings::before{border-color:#d2d2d2;}#copy-path{color:#999;}#copy-path>img{filter:invert(50%);}#copy-path:hover>img{filter:invert(65%);}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}.search-results .result-name span.alias{color:#fff;}.search-results .result-name span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.scraped-example-list .scrape-help{border-color:#aaa;color:#eee;}.scraped-example-list .scrape-help:hover{border-color:white;color:white;}.more-examples-toggle summary,.more-examples-toggle .hide-more{color:#999;}.scraped-example .example-wrap .rust span.highlight{background:rgb(91,59,1);}.scraped-example .example-wrap .rust span.highlight.focus{background:rgb(124,75,15);}.scraped-example:not(.expanded) .code-wrapper:before{background:linear-gradient(to bottom,rgba(53,53,53,1),rgba(53,53,53,0));}.scraped-example:not(.expanded) .code-wrapper:after{background:linear-gradient(to top,rgba(53,53,53,1),rgba(53,53,53,0));}.toggle-line-inner{background:#999;}.toggle-line:hover .toggle-line-inner{background:#c5c5c5;} \ No newline at end of file diff --git a/down-arrow.svg b/down-arrow.svg new file mode 100644 index 00000000..35437e77 --- /dev/null +++ b/down-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/favicon-16x16.png b/favicon-16x16.png new file mode 100644 index 00000000..ea4b45ca Binary files /dev/null and b/favicon-16x16.png differ diff --git a/favicon-32x32.png b/favicon-32x32.png new file mode 100644 index 00000000..69b8613c Binary files /dev/null and b/favicon-32x32.png differ diff --git a/favicon.svg b/favicon.svg new file mode 100644 index 00000000..8b34b511 --- /dev/null +++ b/favicon.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/implementors/cauchy/trait.Scalar.js b/implementors/cauchy/trait.Scalar.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/cauchy/trait.Scalar.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/clone/trait.Clone.js b/implementors/core/clone/trait.Clone.js new file mode 100644 index 00000000..12d95966 --- /dev/null +++ b/implementors/core/clone/trait.Clone.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Clone for MatrixLayout","synthetic":false,"types":["lax::layout::MatrixLayout"]},{"text":"impl Clone for UVTFlag","synthetic":false,"types":["lax::svddc::UVTFlag"]},{"text":"impl Clone for Diag","synthetic":false,"types":["lax::triangular::Diag"]},{"text":"impl<A: Clone + Scalar> Clone for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A: Clone + Scalar> Clone for LUFactorizedTridiagonal<A> where
    A::Real: Clone
","synthetic":false,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl Clone for UPLO","synthetic":false,"types":["lax::UPLO"]},{"text":"impl Clone for Transpose","synthetic":false,"types":["lax::Transpose"]},{"text":"impl Clone for NormType","synthetic":false,"types":["lax::NormType"]},{"text":"impl Clone for EigenVectorFlag","synthetic":false,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl<A: Clone + Scalar> Clone for Householder<A> where
    A::Real: Clone
","synthetic":false,"types":["ndarray_linalg::krylov::householder::Householder"]},{"text":"impl<A: Clone + Scalar> Clone for MGS<A> where
    A::Real: Clone
","synthetic":false,"types":["ndarray_linalg::krylov::mgs::MGS"]},{"text":"impl Clone for Strategy","synthetic":false,"types":["ndarray_linalg::krylov::Strategy"]},{"text":"impl<E: Clone + Scalar, I: Clone + Dimension> Clone for LeastSquaresResult<E, I> where
    E::Real: Clone,
    E::Real: Clone,
    I::Smaller: Clone
","synthetic":false,"types":["ndarray_linalg::least_squares::LeastSquaresResult"]},{"text":"impl Clone for Order","synthetic":false,"types":["ndarray_linalg::lobpcg::lobpcg::Order"]},{"text":"impl<S: Clone + Data + RawDataClone> Clone for LUFactorized<S>","synthetic":false,"types":["ndarray_linalg::solve::LUFactorized"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/cmp/trait.Eq.js b/implementors/core/cmp/trait.Eq.js new file mode 100644 index 00000000..7ed8cd01 --- /dev/null +++ b/implementors/core/cmp/trait.Eq.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Eq for MatrixLayout","synthetic":false,"types":["lax::layout::MatrixLayout"]},{"text":"impl Eq for UVTFlag","synthetic":false,"types":["lax::svddc::UVTFlag"]},{"text":"impl<A: Eq + Scalar> Eq for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl Eq for EigenVectorFlag","synthetic":false,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl Eq for Strategy","synthetic":false,"types":["ndarray_linalg::krylov::Strategy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/cmp/trait.PartialEq.js b/implementors/core/cmp/trait.PartialEq.js new file mode 100644 index 00000000..45b59635 --- /dev/null +++ b/implementors/core/cmp/trait.PartialEq.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl PartialEq<MatrixLayout> for MatrixLayout","synthetic":false,"types":["lax::layout::MatrixLayout"]},{"text":"impl PartialEq<UVTFlag> for UVTFlag","synthetic":false,"types":["lax::svddc::UVTFlag"]},{"text":"impl<A: PartialEq + Scalar> PartialEq<Tridiagonal<A>> for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A: PartialEq + Scalar> PartialEq<LUFactorizedTridiagonal<A>> for LUFactorizedTridiagonal<A> where
    A::Real: PartialEq
","synthetic":false,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl PartialEq<EigenVectorFlag> for EigenVectorFlag","synthetic":false,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl PartialEq<Strategy> for Strategy","synthetic":false,"types":["ndarray_linalg::krylov::Strategy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/convert/trait.From.js b/implementors/core/convert/trait.From.js new file mode 100644 index 00000000..0157b1b5 --- /dev/null +++ b/implementors/core/convert/trait.From.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = [{"text":"impl From<Error> for LinalgError","synthetic":false,"types":["ndarray_linalg::error::LinalgError"]},{"text":"impl From<ShapeError> for LinalgError","synthetic":false,"types":["ndarray_linalg::error::LinalgError"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/fmt/trait.Debug.js b/implementors/core/fmt/trait.Debug.js new file mode 100644 index 00000000..2bc2e4d6 --- /dev/null +++ b/implementors/core/fmt/trait.Debug.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Debug for Error","synthetic":false,"types":["lax::error::Error"]},{"text":"impl Debug for MatrixLayout","synthetic":false,"types":["lax::layout::MatrixLayout"]},{"text":"impl Debug for Diag","synthetic":false,"types":["lax::triangular::Diag"]},{"text":"impl Debug for UPLO","synthetic":false,"types":["lax::UPLO"]},{"text":"impl Debug for Transpose","synthetic":false,"types":["lax::Transpose"]},{"text":"impl Debug for NormType","synthetic":false,"types":["lax::NormType"]},{"text":"impl Debug for EigenVectorFlag","synthetic":false,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl Debug for LinalgError","synthetic":false,"types":["ndarray_linalg::error::LinalgError"]},{"text":"impl<A: Debug + Scalar> Debug for Householder<A> where
    A::Real: Debug
","synthetic":false,"types":["ndarray_linalg::krylov::householder::Householder"]},{"text":"impl<A: Debug + Scalar> Debug for MGS<A> where
    A::Real: Debug
","synthetic":false,"types":["ndarray_linalg::krylov::mgs::MGS"]},{"text":"impl Debug for Strategy","synthetic":false,"types":["ndarray_linalg::krylov::Strategy"]},{"text":"impl<E: Debug + Scalar, I: Debug + Dimension> Debug for LeastSquaresResult<E, I> where
    E::Real: Debug,
    E::Real: Debug,
    I::Smaller: Debug
","synthetic":false,"types":["ndarray_linalg::least_squares::LeastSquaresResult"]},{"text":"impl Debug for Order","synthetic":false,"types":["ndarray_linalg::lobpcg::lobpcg::Order"]},{"text":"impl<A: Debug> Debug for LobpcgResult<A>","synthetic":false,"types":["ndarray_linalg::lobpcg::lobpcg::LobpcgResult"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/fmt/trait.Display.js b/implementors/core/fmt/trait.Display.js new file mode 100644 index 00000000..cf038d06 --- /dev/null +++ b/implementors/core/fmt/trait.Display.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Display for Error","synthetic":false,"types":["lax::error::Error"]}]; +implementors["ndarray_linalg"] = [{"text":"impl Display for LinalgError","synthetic":false,"types":["ndarray_linalg::error::LinalgError"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/iter/traits/collect/trait.IntoIterator.js b/implementors/core/iter/traits/collect/trait.IntoIterator.js new file mode 100644 index 00000000..7c4fe86a --- /dev/null +++ b/implementors/core/iter/traits/collect/trait.IntoIterator.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = [{"text":"impl<A: Float + Scalar + ScalarOperand + Lapack + PartialOrd + Default> IntoIterator for TruncatedEig<A>","synthetic":false,"types":["ndarray_linalg::lobpcg::eig::TruncatedEig"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/iter/traits/iterator/trait.Iterator.js b/implementors/core/iter/traits/iterator/trait.Iterator.js new file mode 100644 index 00000000..93698464 --- /dev/null +++ b/implementors/core/iter/traits/iterator/trait.Iterator.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = [{"text":"impl<A, S, F, Ortho> Iterator for Arnoldi<A, S, F, Ortho> where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
    F: LinearOperator<Elem = A>,
    Ortho: Orthogonalizer<Elem = A>, 
","synthetic":false,"types":["ndarray_linalg::krylov::arnoldi::Arnoldi"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/marker/trait.Copy.js b/implementors/core/marker/trait.Copy.js new file mode 100644 index 00000000..9ed73207 --- /dev/null +++ b/implementors/core/marker/trait.Copy.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Copy for MatrixLayout","synthetic":false,"types":["lax::layout::MatrixLayout"]},{"text":"impl Copy for UVTFlag","synthetic":false,"types":["lax::svddc::UVTFlag"]},{"text":"impl Copy for Diag","synthetic":false,"types":["lax::triangular::Diag"]},{"text":"impl Copy for UPLO","synthetic":false,"types":["lax::UPLO"]},{"text":"impl Copy for Transpose","synthetic":false,"types":["lax::Transpose"]},{"text":"impl Copy for NormType","synthetic":false,"types":["lax::NormType"]},{"text":"impl Copy for EigenVectorFlag","synthetic":false,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl Copy for Strategy","synthetic":false,"types":["ndarray_linalg::krylov::Strategy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/marker/trait.Freeze.js b/implementors/core/marker/trait.Freeze.js new file mode 100644 index 00000000..7c6aa34d --- /dev/null +++ b/implementors/core/marker/trait.Freeze.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Freeze for Error","synthetic":true,"types":["lax::error::Error"]},{"text":"impl Freeze for MatrixLayout","synthetic":true,"types":["lax::layout::MatrixLayout"]},{"text":"impl<A> Freeze for LeastSquaresOutput<A>","synthetic":true,"types":["lax::least_squares::LeastSquaresOutput"]},{"text":"impl<A> Freeze for SVDOutput<A>","synthetic":true,"types":["lax::svd::SVDOutput"]},{"text":"impl Freeze for UVTFlag","synthetic":true,"types":["lax::svddc::UVTFlag"]},{"text":"impl Freeze for Diag","synthetic":true,"types":["lax::triangular::Diag"]},{"text":"impl<A> Freeze for Tridiagonal<A>","synthetic":true,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A> Freeze for LUFactorizedTridiagonal<A> where
    <A as Scalar>::Real: Freeze, 
","synthetic":true,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl Freeze for UPLO","synthetic":true,"types":["lax::UPLO"]},{"text":"impl Freeze for Transpose","synthetic":true,"types":["lax::Transpose"]},{"text":"impl Freeze for NormType","synthetic":true,"types":["lax::NormType"]},{"text":"impl Freeze for EigenVectorFlag","synthetic":true,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl<S> Freeze for CholeskyFactorized<S> where
    S: Freeze, 
","synthetic":true,"types":["ndarray_linalg::cholesky::CholeskyFactorized"]},{"text":"impl<S> Freeze for Diagonal<S> where
    S: Freeze, 
","synthetic":true,"types":["ndarray_linalg::diagonal::Diagonal"]},{"text":"impl Freeze for LinalgError","synthetic":true,"types":["ndarray_linalg::error::LinalgError"]},{"text":"impl<A, S, F, Ortho> Freeze for Arnoldi<A, S, F, Ortho> where
    F: Freeze,
    Ortho: Freeze,
    S: Freeze, 
","synthetic":true,"types":["ndarray_linalg::krylov::arnoldi::Arnoldi"]},{"text":"impl<A> Freeze for Householder<A> where
    <A as Scalar>::Real: Freeze, 
","synthetic":true,"types":["ndarray_linalg::krylov::householder::Householder"]},{"text":"impl<A> Freeze for MGS<A> where
    <A as Scalar>::Real: Freeze, 
","synthetic":true,"types":["ndarray_linalg::krylov::mgs::MGS"]},{"text":"impl<A> Freeze for AppendResult<A>","synthetic":true,"types":["ndarray_linalg::krylov::AppendResult"]},{"text":"impl Freeze for Strategy","synthetic":true,"types":["ndarray_linalg::krylov::Strategy"]},{"text":"impl<E, I> Freeze for LeastSquaresResult<E, I> where
    I: Freeze,
    <I as Dimension>::Smaller: Freeze, 
","synthetic":true,"types":["ndarray_linalg::least_squares::LeastSquaresResult"]},{"text":"impl<A> Freeze for TruncatedEig<A>","synthetic":true,"types":["ndarray_linalg::lobpcg::eig::TruncatedEig"]},{"text":"impl Freeze for Order","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::Order"]},{"text":"impl<A> Freeze for LobpcgResult<A>","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::LobpcgResult"]},{"text":"impl<A> Freeze for TruncatedSvd<A>","synthetic":true,"types":["ndarray_linalg::lobpcg::svd::TruncatedSvd"]},{"text":"impl Freeze for NormalizeAxis","synthetic":true,"types":["ndarray_linalg::norm::NormalizeAxis"]},{"text":"impl<S> Freeze for LUFactorized<S> where
    S: Freeze, 
","synthetic":true,"types":["ndarray_linalg::solve::LUFactorized"]},{"text":"impl<S> Freeze for BKFactorized<S> where
    S: Freeze, 
","synthetic":true,"types":["ndarray_linalg::solveh::BKFactorized"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/marker/trait.Send.js b/implementors/core/marker/trait.Send.js new file mode 100644 index 00000000..330de8da --- /dev/null +++ b/implementors/core/marker/trait.Send.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Send for Error","synthetic":true,"types":["lax::error::Error"]},{"text":"impl Send for MatrixLayout","synthetic":true,"types":["lax::layout::MatrixLayout"]},{"text":"impl<A> Send for LeastSquaresOutput<A> where
    <A as Scalar>::Real: Send
","synthetic":true,"types":["lax::least_squares::LeastSquaresOutput"]},{"text":"impl<A> Send for SVDOutput<A> where
    A: Send,
    <A as Scalar>::Real: Send
","synthetic":true,"types":["lax::svd::SVDOutput"]},{"text":"impl Send for UVTFlag","synthetic":true,"types":["lax::svddc::UVTFlag"]},{"text":"impl Send for Diag","synthetic":true,"types":["lax::triangular::Diag"]},{"text":"impl<A> Send for Tridiagonal<A> where
    A: Send
","synthetic":true,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A> Send for LUFactorizedTridiagonal<A> where
    A: Send,
    <A as Scalar>::Real: Send
","synthetic":true,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl Send for UPLO","synthetic":true,"types":["lax::UPLO"]},{"text":"impl Send for Transpose","synthetic":true,"types":["lax::Transpose"]},{"text":"impl Send for NormType","synthetic":true,"types":["lax::NormType"]},{"text":"impl Send for EigenVectorFlag","synthetic":true,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl<S> Send for CholeskyFactorized<S> where
    S: Send
","synthetic":true,"types":["ndarray_linalg::cholesky::CholeskyFactorized"]},{"text":"impl<S> Send for Diagonal<S> where
    S: Send
","synthetic":true,"types":["ndarray_linalg::diagonal::Diagonal"]},{"text":"impl Send for LinalgError","synthetic":true,"types":["ndarray_linalg::error::LinalgError"]},{"text":"impl<A, S, F, Ortho> Send for Arnoldi<A, S, F, Ortho> where
    A: Send,
    F: Send,
    Ortho: Send,
    S: Send
","synthetic":true,"types":["ndarray_linalg::krylov::arnoldi::Arnoldi"]},{"text":"impl<A> Send for Householder<A> where
    A: Send,
    <A as Scalar>::Real: Send
","synthetic":true,"types":["ndarray_linalg::krylov::householder::Householder"]},{"text":"impl<A> Send for MGS<A> where
    A: Send,
    <A as Scalar>::Real: Send
","synthetic":true,"types":["ndarray_linalg::krylov::mgs::MGS"]},{"text":"impl<A> Send for AppendResult<A> where
    A: Send
","synthetic":true,"types":["ndarray_linalg::krylov::AppendResult"]},{"text":"impl Send for Strategy","synthetic":true,"types":["ndarray_linalg::krylov::Strategy"]},{"text":"impl<E, I> Send for LeastSquaresResult<E, I> where
    E: Send,
    <E as Scalar>::Real: Send
","synthetic":true,"types":["ndarray_linalg::least_squares::LeastSquaresResult"]},{"text":"impl<A> Send for TruncatedEig<A> where
    A: Send
","synthetic":true,"types":["ndarray_linalg::lobpcg::eig::TruncatedEig"]},{"text":"impl Send for Order","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::Order"]},{"text":"impl<A> Send for LobpcgResult<A> where
    A: Send
","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::LobpcgResult"]},{"text":"impl<A> Send for TruncatedSvd<A> where
    A: Send
","synthetic":true,"types":["ndarray_linalg::lobpcg::svd::TruncatedSvd"]},{"text":"impl Send for NormalizeAxis","synthetic":true,"types":["ndarray_linalg::norm::NormalizeAxis"]},{"text":"impl<S> Send for LUFactorized<S> where
    S: Send
","synthetic":true,"types":["ndarray_linalg::solve::LUFactorized"]},{"text":"impl<S> Send for BKFactorized<S> where
    S: Send
","synthetic":true,"types":["ndarray_linalg::solveh::BKFactorized"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/marker/trait.StructuralEq.js b/implementors/core/marker/trait.StructuralEq.js new file mode 100644 index 00000000..7e7a7afa --- /dev/null +++ b/implementors/core/marker/trait.StructuralEq.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl StructuralEq for MatrixLayout","synthetic":false,"types":["lax::layout::MatrixLayout"]},{"text":"impl StructuralEq for UVTFlag","synthetic":false,"types":["lax::svddc::UVTFlag"]},{"text":"impl<A: Scalar> StructuralEq for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl StructuralEq for EigenVectorFlag","synthetic":false,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl StructuralEq for Strategy","synthetic":false,"types":["ndarray_linalg::krylov::Strategy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/marker/trait.StructuralPartialEq.js b/implementors/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 00000000..b723fa6e --- /dev/null +++ b/implementors/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl StructuralPartialEq for MatrixLayout","synthetic":false,"types":["lax::layout::MatrixLayout"]},{"text":"impl StructuralPartialEq for UVTFlag","synthetic":false,"types":["lax::svddc::UVTFlag"]},{"text":"impl<A: Scalar> StructuralPartialEq for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A: Scalar> StructuralPartialEq for LUFactorizedTridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl StructuralPartialEq for EigenVectorFlag","synthetic":false,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl StructuralPartialEq for Strategy","synthetic":false,"types":["ndarray_linalg::krylov::Strategy"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/marker/trait.Sync.js b/implementors/core/marker/trait.Sync.js new file mode 100644 index 00000000..b29844e4 --- /dev/null +++ b/implementors/core/marker/trait.Sync.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Sync for Error","synthetic":true,"types":["lax::error::Error"]},{"text":"impl Sync for MatrixLayout","synthetic":true,"types":["lax::layout::MatrixLayout"]},{"text":"impl<A> Sync for LeastSquaresOutput<A> where
    <A as Scalar>::Real: Sync
","synthetic":true,"types":["lax::least_squares::LeastSquaresOutput"]},{"text":"impl<A> Sync for SVDOutput<A> where
    A: Sync,
    <A as Scalar>::Real: Sync
","synthetic":true,"types":["lax::svd::SVDOutput"]},{"text":"impl Sync for UVTFlag","synthetic":true,"types":["lax::svddc::UVTFlag"]},{"text":"impl Sync for Diag","synthetic":true,"types":["lax::triangular::Diag"]},{"text":"impl<A> Sync for Tridiagonal<A> where
    A: Sync
","synthetic":true,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A> Sync for LUFactorizedTridiagonal<A> where
    A: Sync,
    <A as Scalar>::Real: Sync
","synthetic":true,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl Sync for UPLO","synthetic":true,"types":["lax::UPLO"]},{"text":"impl Sync for Transpose","synthetic":true,"types":["lax::Transpose"]},{"text":"impl Sync for NormType","synthetic":true,"types":["lax::NormType"]},{"text":"impl Sync for EigenVectorFlag","synthetic":true,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl<S> Sync for CholeskyFactorized<S> where
    S: Sync
","synthetic":true,"types":["ndarray_linalg::cholesky::CholeskyFactorized"]},{"text":"impl<S> Sync for Diagonal<S> where
    S: Sync
","synthetic":true,"types":["ndarray_linalg::diagonal::Diagonal"]},{"text":"impl Sync for LinalgError","synthetic":true,"types":["ndarray_linalg::error::LinalgError"]},{"text":"impl<A, S, F, Ortho> Sync for Arnoldi<A, S, F, Ortho> where
    A: Sync,
    F: Sync,
    Ortho: Sync,
    S: Sync
","synthetic":true,"types":["ndarray_linalg::krylov::arnoldi::Arnoldi"]},{"text":"impl<A> Sync for Householder<A> where
    A: Sync,
    <A as Scalar>::Real: Sync
","synthetic":true,"types":["ndarray_linalg::krylov::householder::Householder"]},{"text":"impl<A> Sync for MGS<A> where
    A: Sync,
    <A as Scalar>::Real: Sync
","synthetic":true,"types":["ndarray_linalg::krylov::mgs::MGS"]},{"text":"impl<A> Sync for AppendResult<A> where
    A: Sync
","synthetic":true,"types":["ndarray_linalg::krylov::AppendResult"]},{"text":"impl Sync for Strategy","synthetic":true,"types":["ndarray_linalg::krylov::Strategy"]},{"text":"impl<E, I> Sync for LeastSquaresResult<E, I> where
    E: Sync,
    <E as Scalar>::Real: Sync
","synthetic":true,"types":["ndarray_linalg::least_squares::LeastSquaresResult"]},{"text":"impl<A> Sync for TruncatedEig<A> where
    A: Sync
","synthetic":true,"types":["ndarray_linalg::lobpcg::eig::TruncatedEig"]},{"text":"impl Sync for Order","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::Order"]},{"text":"impl<A> Sync for LobpcgResult<A> where
    A: Sync
","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::LobpcgResult"]},{"text":"impl<A> Sync for TruncatedSvd<A> where
    A: Sync
","synthetic":true,"types":["ndarray_linalg::lobpcg::svd::TruncatedSvd"]},{"text":"impl Sync for NormalizeAxis","synthetic":true,"types":["ndarray_linalg::norm::NormalizeAxis"]},{"text":"impl<S> Sync for LUFactorized<S> where
    S: Sync
","synthetic":true,"types":["ndarray_linalg::solve::LUFactorized"]},{"text":"impl<S> Sync for BKFactorized<S> where
    S: Sync
","synthetic":true,"types":["ndarray_linalg::solveh::BKFactorized"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/marker/trait.Unpin.js b/implementors/core/marker/trait.Unpin.js new file mode 100644 index 00000000..6c5f2a79 --- /dev/null +++ b/implementors/core/marker/trait.Unpin.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Unpin for Error","synthetic":true,"types":["lax::error::Error"]},{"text":"impl Unpin for MatrixLayout","synthetic":true,"types":["lax::layout::MatrixLayout"]},{"text":"impl<A> Unpin for LeastSquaresOutput<A> where
    <A as Scalar>::Real: Unpin
","synthetic":true,"types":["lax::least_squares::LeastSquaresOutput"]},{"text":"impl<A> Unpin for SVDOutput<A> where
    A: Unpin,
    <A as Scalar>::Real: Unpin
","synthetic":true,"types":["lax::svd::SVDOutput"]},{"text":"impl Unpin for UVTFlag","synthetic":true,"types":["lax::svddc::UVTFlag"]},{"text":"impl Unpin for Diag","synthetic":true,"types":["lax::triangular::Diag"]},{"text":"impl<A> Unpin for Tridiagonal<A> where
    A: Unpin
","synthetic":true,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A> Unpin for LUFactorizedTridiagonal<A> where
    A: Unpin,
    <A as Scalar>::Real: Unpin
","synthetic":true,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl Unpin for UPLO","synthetic":true,"types":["lax::UPLO"]},{"text":"impl Unpin for Transpose","synthetic":true,"types":["lax::Transpose"]},{"text":"impl Unpin for NormType","synthetic":true,"types":["lax::NormType"]},{"text":"impl Unpin for EigenVectorFlag","synthetic":true,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl<S> Unpin for CholeskyFactorized<S> where
    S: Unpin
","synthetic":true,"types":["ndarray_linalg::cholesky::CholeskyFactorized"]},{"text":"impl<S> Unpin for Diagonal<S> where
    S: Unpin
","synthetic":true,"types":["ndarray_linalg::diagonal::Diagonal"]},{"text":"impl Unpin for LinalgError","synthetic":true,"types":["ndarray_linalg::error::LinalgError"]},{"text":"impl<A, S, F, Ortho> Unpin for Arnoldi<A, S, F, Ortho> where
    F: Unpin,
    Ortho: Unpin,
    S: Unpin
","synthetic":true,"types":["ndarray_linalg::krylov::arnoldi::Arnoldi"]},{"text":"impl<A> Unpin for Householder<A> where
    <A as Scalar>::Real: Unpin
","synthetic":true,"types":["ndarray_linalg::krylov::householder::Householder"]},{"text":"impl<A> Unpin for MGS<A> where
    <A as Scalar>::Real: Unpin
","synthetic":true,"types":["ndarray_linalg::krylov::mgs::MGS"]},{"text":"impl<A> Unpin for AppendResult<A>","synthetic":true,"types":["ndarray_linalg::krylov::AppendResult"]},{"text":"impl Unpin for Strategy","synthetic":true,"types":["ndarray_linalg::krylov::Strategy"]},{"text":"impl<E, I> Unpin for LeastSquaresResult<E, I> where
    I: Unpin,
    <I as Dimension>::Smaller: Unpin
","synthetic":true,"types":["ndarray_linalg::least_squares::LeastSquaresResult"]},{"text":"impl<A> Unpin for TruncatedEig<A>","synthetic":true,"types":["ndarray_linalg::lobpcg::eig::TruncatedEig"]},{"text":"impl Unpin for Order","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::Order"]},{"text":"impl<A> Unpin for LobpcgResult<A> where
    A: Unpin
","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::LobpcgResult"]},{"text":"impl<A> Unpin for TruncatedSvd<A>","synthetic":true,"types":["ndarray_linalg::lobpcg::svd::TruncatedSvd"]},{"text":"impl Unpin for NormalizeAxis","synthetic":true,"types":["ndarray_linalg::norm::NormalizeAxis"]},{"text":"impl<S> Unpin for LUFactorized<S> where
    S: Unpin
","synthetic":true,"types":["ndarray_linalg::solve::LUFactorized"]},{"text":"impl<S> Unpin for BKFactorized<S> where
    S: Unpin
","synthetic":true,"types":["ndarray_linalg::solveh::BKFactorized"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/ops/index/trait.Index.js b/implementors/core/ops/index/trait.Index.js new file mode 100644 index 00000000..ccf1d1b8 --- /dev/null +++ b/implementors/core/ops/index/trait.Index.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl<A: Scalar> Index<(i32, i32)> for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A: Scalar> Index<[i32; 2]> for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/ops/index/trait.IndexMut.js b/implementors/core/ops/index/trait.IndexMut.js new file mode 100644 index 00000000..fe9cdba3 --- /dev/null +++ b/implementors/core/ops/index/trait.IndexMut.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl<A: Scalar> IndexMut<(i32, i32)> for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A: Scalar> IndexMut<[i32; 2]> for Tridiagonal<A>","synthetic":false,"types":["lax::tridiagonal::Tridiagonal"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js b/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js new file mode 100644 index 00000000..302790c5 --- /dev/null +++ b/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":["lax::error::Error"]},{"text":"impl RefUnwindSafe for MatrixLayout","synthetic":true,"types":["lax::layout::MatrixLayout"]},{"text":"impl<A> RefUnwindSafe for LeastSquaresOutput<A> where
    <A as Scalar>::Real: RefUnwindSafe
","synthetic":true,"types":["lax::least_squares::LeastSquaresOutput"]},{"text":"impl<A> RefUnwindSafe for SVDOutput<A> where
    A: RefUnwindSafe,
    <A as Scalar>::Real: RefUnwindSafe
","synthetic":true,"types":["lax::svd::SVDOutput"]},{"text":"impl RefUnwindSafe for UVTFlag","synthetic":true,"types":["lax::svddc::UVTFlag"]},{"text":"impl RefUnwindSafe for Diag","synthetic":true,"types":["lax::triangular::Diag"]},{"text":"impl<A> RefUnwindSafe for Tridiagonal<A> where
    A: RefUnwindSafe
","synthetic":true,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A> RefUnwindSafe for LUFactorizedTridiagonal<A> where
    A: RefUnwindSafe,
    <A as Scalar>::Real: RefUnwindSafe
","synthetic":true,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl RefUnwindSafe for UPLO","synthetic":true,"types":["lax::UPLO"]},{"text":"impl RefUnwindSafe for Transpose","synthetic":true,"types":["lax::Transpose"]},{"text":"impl RefUnwindSafe for NormType","synthetic":true,"types":["lax::NormType"]},{"text":"impl RefUnwindSafe for EigenVectorFlag","synthetic":true,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl<S> RefUnwindSafe for CholeskyFactorized<S> where
    S: RefUnwindSafe,
    <S as RawData>::Elem: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::cholesky::CholeskyFactorized"]},{"text":"impl<S> RefUnwindSafe for Diagonal<S> where
    S: RefUnwindSafe,
    <S as RawData>::Elem: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::diagonal::Diagonal"]},{"text":"impl RefUnwindSafe for LinalgError","synthetic":true,"types":["ndarray_linalg::error::LinalgError"]},{"text":"impl<A, S, F, Ortho> RefUnwindSafe for Arnoldi<A, S, F, Ortho> where
    A: RefUnwindSafe,
    F: RefUnwindSafe,
    Ortho: RefUnwindSafe,
    S: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::krylov::arnoldi::Arnoldi"]},{"text":"impl<A> RefUnwindSafe for Householder<A> where
    A: RefUnwindSafe,
    <A as Scalar>::Real: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::krylov::householder::Householder"]},{"text":"impl<A> RefUnwindSafe for MGS<A> where
    A: RefUnwindSafe,
    <A as Scalar>::Real: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::krylov::mgs::MGS"]},{"text":"impl<A> RefUnwindSafe for AppendResult<A> where
    A: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::krylov::AppendResult"]},{"text":"impl RefUnwindSafe for Strategy","synthetic":true,"types":["ndarray_linalg::krylov::Strategy"]},{"text":"impl<E, I> RefUnwindSafe for LeastSquaresResult<E, I> where
    E: RefUnwindSafe,
    I: RefUnwindSafe,
    <E as Scalar>::Real: RefUnwindSafe,
    <I as Dimension>::Smaller: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::least_squares::LeastSquaresResult"]},{"text":"impl<A> RefUnwindSafe for TruncatedEig<A> where
    A: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::lobpcg::eig::TruncatedEig"]},{"text":"impl RefUnwindSafe for Order","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::Order"]},{"text":"impl<A> RefUnwindSafe for LobpcgResult<A> where
    A: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::LobpcgResult"]},{"text":"impl<A> RefUnwindSafe for TruncatedSvd<A> where
    A: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::lobpcg::svd::TruncatedSvd"]},{"text":"impl RefUnwindSafe for NormalizeAxis","synthetic":true,"types":["ndarray_linalg::norm::NormalizeAxis"]},{"text":"impl<S> RefUnwindSafe for LUFactorized<S> where
    S: RefUnwindSafe,
    <S as RawData>::Elem: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::solve::LUFactorized"]},{"text":"impl<S> RefUnwindSafe for BKFactorized<S> where
    S: RefUnwindSafe,
    <S as RawData>::Elem: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::solveh::BKFactorized"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/core/panic/unwind_safe/trait.UnwindSafe.js b/implementors/core/panic/unwind_safe/trait.UnwindSafe.js new file mode 100644 index 00000000..fea4b6a2 --- /dev/null +++ b/implementors/core/panic/unwind_safe/trait.UnwindSafe.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl UnwindSafe for Error","synthetic":true,"types":["lax::error::Error"]},{"text":"impl UnwindSafe for MatrixLayout","synthetic":true,"types":["lax::layout::MatrixLayout"]},{"text":"impl<A> UnwindSafe for LeastSquaresOutput<A> where
    <A as Scalar>::Real: UnwindSafe
","synthetic":true,"types":["lax::least_squares::LeastSquaresOutput"]},{"text":"impl<A> UnwindSafe for SVDOutput<A> where
    A: UnwindSafe,
    <A as Scalar>::Real: UnwindSafe
","synthetic":true,"types":["lax::svd::SVDOutput"]},{"text":"impl UnwindSafe for UVTFlag","synthetic":true,"types":["lax::svddc::UVTFlag"]},{"text":"impl UnwindSafe for Diag","synthetic":true,"types":["lax::triangular::Diag"]},{"text":"impl<A> UnwindSafe for Tridiagonal<A> where
    A: UnwindSafe
","synthetic":true,"types":["lax::tridiagonal::Tridiagonal"]},{"text":"impl<A> UnwindSafe for LUFactorizedTridiagonal<A> where
    A: UnwindSafe,
    <A as Scalar>::Real: UnwindSafe
","synthetic":true,"types":["lax::tridiagonal::LUFactorizedTridiagonal"]},{"text":"impl UnwindSafe for UPLO","synthetic":true,"types":["lax::UPLO"]},{"text":"impl UnwindSafe for Transpose","synthetic":true,"types":["lax::Transpose"]},{"text":"impl UnwindSafe for NormType","synthetic":true,"types":["lax::NormType"]},{"text":"impl UnwindSafe for EigenVectorFlag","synthetic":true,"types":["lax::EigenVectorFlag"]}]; +implementors["ndarray_linalg"] = [{"text":"impl<S> UnwindSafe for CholeskyFactorized<S> where
    S: UnwindSafe,
    <S as RawData>::Elem: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::cholesky::CholeskyFactorized"]},{"text":"impl<S> UnwindSafe for Diagonal<S> where
    S: UnwindSafe,
    <S as RawData>::Elem: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::diagonal::Diagonal"]},{"text":"impl UnwindSafe for LinalgError","synthetic":true,"types":["ndarray_linalg::error::LinalgError"]},{"text":"impl<A, S, F, Ortho> UnwindSafe for Arnoldi<A, S, F, Ortho> where
    A: RefUnwindSafe,
    F: UnwindSafe,
    Ortho: UnwindSafe,
    S: UnwindSafe
","synthetic":true,"types":["ndarray_linalg::krylov::arnoldi::Arnoldi"]},{"text":"impl<A> UnwindSafe for Householder<A> where
    A: RefUnwindSafe,
    <A as Scalar>::Real: UnwindSafe
","synthetic":true,"types":["ndarray_linalg::krylov::householder::Householder"]},{"text":"impl<A> UnwindSafe for MGS<A> where
    A: RefUnwindSafe,
    <A as Scalar>::Real: UnwindSafe
","synthetic":true,"types":["ndarray_linalg::krylov::mgs::MGS"]},{"text":"impl<A> UnwindSafe for AppendResult<A> where
    A: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::krylov::AppendResult"]},{"text":"impl UnwindSafe for Strategy","synthetic":true,"types":["ndarray_linalg::krylov::Strategy"]},{"text":"impl<E, I> UnwindSafe for LeastSquaresResult<E, I> where
    E: RefUnwindSafe,
    I: UnwindSafe,
    <E as Scalar>::Real: RefUnwindSafe,
    <I as Dimension>::Smaller: UnwindSafe
","synthetic":true,"types":["ndarray_linalg::least_squares::LeastSquaresResult"]},{"text":"impl<A> UnwindSafe for TruncatedEig<A> where
    A: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::lobpcg::eig::TruncatedEig"]},{"text":"impl UnwindSafe for Order","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::Order"]},{"text":"impl<A> UnwindSafe for LobpcgResult<A> where
    A: UnwindSafe + RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::lobpcg::lobpcg::LobpcgResult"]},{"text":"impl<A> UnwindSafe for TruncatedSvd<A> where
    A: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::lobpcg::svd::TruncatedSvd"]},{"text":"impl UnwindSafe for NormalizeAxis","synthetic":true,"types":["ndarray_linalg::norm::NormalizeAxis"]},{"text":"impl<S> UnwindSafe for LUFactorized<S> where
    S: UnwindSafe,
    <S as RawData>::Elem: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::solve::LUFactorized"]},{"text":"impl<S> UnwindSafe for BKFactorized<S> where
    S: UnwindSafe,
    <S as RawData>::Elem: RefUnwindSafe
","synthetic":true,"types":["ndarray_linalg::solveh::BKFactorized"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/cholesky/trait.Cholesky_.js b/implementors/lax/cholesky/trait.Cholesky_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/cholesky/trait.Cholesky_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/eig/trait.Eig_.js b/implementors/lax/eig/trait.Eig_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/eig/trait.Eig_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/eigh/trait.Eigh_.js b/implementors/lax/eigh/trait.Eigh_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/eigh/trait.Eigh_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/error/trait.AsLapackResult.js b/implementors/lax/error/trait.AsLapackResult.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/error/trait.AsLapackResult.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/least_squares/trait.LeastSquaresSvdDivideConquer_.js b/implementors/lax/least_squares/trait.LeastSquaresSvdDivideConquer_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/least_squares/trait.LeastSquaresSvdDivideConquer_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/opnorm/trait.OperatorNorm_.js b/implementors/lax/opnorm/trait.OperatorNorm_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/opnorm/trait.OperatorNorm_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/qr/trait.QR_.js b/implementors/lax/qr/trait.QR_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/qr/trait.QR_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/rcond/trait.Rcond_.js b/implementors/lax/rcond/trait.Rcond_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/rcond/trait.Rcond_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/solve/trait.Solve_.js b/implementors/lax/solve/trait.Solve_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/solve/trait.Solve_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/solveh/trait.Solveh_.js b/implementors/lax/solveh/trait.Solveh_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/solveh/trait.Solveh_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/svd/trait.SVD_.js b/implementors/lax/svd/trait.SVD_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/svd/trait.SVD_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/svddc/trait.SVDDC_.js b/implementors/lax/svddc/trait.SVDDC_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/svddc/trait.SVDDC_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/trait.Lapack.js b/implementors/lax/trait.Lapack.js new file mode 100644 index 00000000..1b372da7 --- /dev/null +++ b/implementors/lax/trait.Lapack.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/triangular/trait.Triangular_.js b/implementors/lax/triangular/trait.Triangular_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/triangular/trait.Triangular_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/lax/tridiagonal/trait.Tridiagonal_.js b/implementors/lax/tridiagonal/trait.Tridiagonal_.js new file mode 100644 index 00000000..a280d509 --- /dev/null +++ b/implementors/lax/tridiagonal/trait.Tridiagonal_.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["lax"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.Cholesky.js b/implementors/ndarray_linalg/cholesky/trait.Cholesky.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.Cholesky.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.CholeskyInplace.js b/implementors/ndarray_linalg/cholesky/trait.CholeskyInplace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.CholeskyInplace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.CholeskyInto.js b/implementors/ndarray_linalg/cholesky/trait.CholeskyInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.CholeskyInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.DeterminantC.js b/implementors/ndarray_linalg/cholesky/trait.DeterminantC.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.DeterminantC.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.DeterminantCInto.js b/implementors/ndarray_linalg/cholesky/trait.DeterminantCInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.DeterminantCInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.FactorizeC.js b/implementors/ndarray_linalg/cholesky/trait.FactorizeC.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.FactorizeC.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.FactorizeCInto.js b/implementors/ndarray_linalg/cholesky/trait.FactorizeCInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.FactorizeCInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.InverseC.js b/implementors/ndarray_linalg/cholesky/trait.InverseC.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.InverseC.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.InverseCInto.js b/implementors/ndarray_linalg/cholesky/trait.InverseCInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.InverseCInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/cholesky/trait.SolveC.js b/implementors/ndarray_linalg/cholesky/trait.SolveC.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/cholesky/trait.SolveC.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/diagonal/trait.AsDiagonal.js b/implementors/ndarray_linalg/diagonal/trait.AsDiagonal.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/diagonal/trait.AsDiagonal.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/diagonal/trait.IntoDiagonal.js b/implementors/ndarray_linalg/diagonal/trait.IntoDiagonal.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/diagonal/trait.IntoDiagonal.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eig/trait.Eig.js b/implementors/ndarray_linalg/eig/trait.Eig.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eig/trait.Eig.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eig/trait.EigVals.js b/implementors/ndarray_linalg/eig/trait.EigVals.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eig/trait.EigVals.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eigh/trait.EigValsh.js b/implementors/ndarray_linalg/eigh/trait.EigValsh.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eigh/trait.EigValsh.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eigh/trait.EigValshInplace.js b/implementors/ndarray_linalg/eigh/trait.EigValshInplace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eigh/trait.EigValshInplace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eigh/trait.EigValshInto.js b/implementors/ndarray_linalg/eigh/trait.EigValshInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eigh/trait.EigValshInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eigh/trait.Eigh.js b/implementors/ndarray_linalg/eigh/trait.Eigh.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eigh/trait.Eigh.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eigh/trait.EighInplace.js b/implementors/ndarray_linalg/eigh/trait.EighInplace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eigh/trait.EighInplace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eigh/trait.EighInto.js b/implementors/ndarray_linalg/eigh/trait.EighInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eigh/trait.EighInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eigh/trait.SymmetricSqrt.js b/implementors/ndarray_linalg/eigh/trait.SymmetricSqrt.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eigh/trait.SymmetricSqrt.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/eigh/trait.SymmetricSqrtInto.js b/implementors/ndarray_linalg/eigh/trait.SymmetricSqrtInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/eigh/trait.SymmetricSqrtInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/inner/trait.InnerProduct.js b/implementors/ndarray_linalg/inner/trait.InnerProduct.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/inner/trait.InnerProduct.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/krylov/trait.Orthogonalizer.js b/implementors/ndarray_linalg/krylov/trait.Orthogonalizer.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/krylov/trait.Orthogonalizer.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/layout/trait.AllocatedArray.js b/implementors/ndarray_linalg/layout/trait.AllocatedArray.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/layout/trait.AllocatedArray.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/layout/trait.AllocatedArrayMut.js b/implementors/ndarray_linalg/layout/trait.AllocatedArrayMut.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/layout/trait.AllocatedArrayMut.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvd.js b/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvd.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvd.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvdInPlace.js b/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvdInPlace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvdInPlace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvdInto.js b/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvdInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/least_squares/trait.LeastSquaresSvdInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/norm/trait.Norm.js b/implementors/ndarray_linalg/norm/trait.Norm.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/norm/trait.Norm.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/operator/trait.LinearOperator.js b/implementors/ndarray_linalg/operator/trait.LinearOperator.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/operator/trait.LinearOperator.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/opnorm/trait.OperationNorm.js b/implementors/ndarray_linalg/opnorm/trait.OperationNorm.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/opnorm/trait.OperationNorm.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/qr/trait.QR.js b/implementors/ndarray_linalg/qr/trait.QR.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/qr/trait.QR.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/qr/trait.QRInto.js b/implementors/ndarray_linalg/qr/trait.QRInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/qr/trait.QRInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/qr/trait.QRSquare.js b/implementors/ndarray_linalg/qr/trait.QRSquare.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/qr/trait.QRSquare.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/qr/trait.QRSquareInplace.js b/implementors/ndarray_linalg/qr/trait.QRSquareInplace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/qr/trait.QRSquareInplace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/qr/trait.QRSquareInto.js b/implementors/ndarray_linalg/qr/trait.QRSquareInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/qr/trait.QRSquareInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.Determinant.js b/implementors/ndarray_linalg/solve/trait.Determinant.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.Determinant.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.DeterminantInto.js b/implementors/ndarray_linalg/solve/trait.DeterminantInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.DeterminantInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.Factorize.js b/implementors/ndarray_linalg/solve/trait.Factorize.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.Factorize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.FactorizeInto.js b/implementors/ndarray_linalg/solve/trait.FactorizeInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.FactorizeInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.Inverse.js b/implementors/ndarray_linalg/solve/trait.Inverse.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.Inverse.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.InverseInto.js b/implementors/ndarray_linalg/solve/trait.InverseInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.InverseInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.ReciprocalConditionNum.js b/implementors/ndarray_linalg/solve/trait.ReciprocalConditionNum.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.ReciprocalConditionNum.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.ReciprocalConditionNumInto.js b/implementors/ndarray_linalg/solve/trait.ReciprocalConditionNumInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.ReciprocalConditionNumInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solve/trait.Solve.js b/implementors/ndarray_linalg/solve/trait.Solve.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solve/trait.Solve.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solveh/trait.DeterminantH.js b/implementors/ndarray_linalg/solveh/trait.DeterminantH.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solveh/trait.DeterminantH.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solveh/trait.DeterminantHInto.js b/implementors/ndarray_linalg/solveh/trait.DeterminantHInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solveh/trait.DeterminantHInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solveh/trait.FactorizeH.js b/implementors/ndarray_linalg/solveh/trait.FactorizeH.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solveh/trait.FactorizeH.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solveh/trait.FactorizeHInto.js b/implementors/ndarray_linalg/solveh/trait.FactorizeHInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solveh/trait.FactorizeHInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solveh/trait.InverseH.js b/implementors/ndarray_linalg/solveh/trait.InverseH.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solveh/trait.InverseH.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solveh/trait.InverseHInto.js b/implementors/ndarray_linalg/solveh/trait.InverseHInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solveh/trait.InverseHInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/solveh/trait.SolveH.js b/implementors/ndarray_linalg/solveh/trait.SolveH.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/solveh/trait.SolveH.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/svd/trait.SVD.js b/implementors/ndarray_linalg/svd/trait.SVD.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/svd/trait.SVD.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/svd/trait.SVDInplace.js b/implementors/ndarray_linalg/svd/trait.SVDInplace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/svd/trait.SVDInplace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/svd/trait.SVDInto.js b/implementors/ndarray_linalg/svd/trait.SVDInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/svd/trait.SVDInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/svddc/trait.SVDDC.js b/implementors/ndarray_linalg/svddc/trait.SVDDC.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/svddc/trait.SVDDC.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/svddc/trait.SVDDCInplace.js b/implementors/ndarray_linalg/svddc/trait.SVDDCInplace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/svddc/trait.SVDDCInplace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/svddc/trait.SVDDCInto.js b/implementors/ndarray_linalg/svddc/trait.SVDDCInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/svddc/trait.SVDDCInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/trace/trait.Trace.js b/implementors/ndarray_linalg/trace/trait.Trace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/trace/trait.Trace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/triangular/trait.IntoTriangular.js b/implementors/ndarray_linalg/triangular/trait.IntoTriangular.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/triangular/trait.IntoTriangular.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/triangular/trait.SolveTriangular.js b/implementors/ndarray_linalg/triangular/trait.SolveTriangular.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/triangular/trait.SolveTriangular.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/triangular/trait.SolveTriangularInplace.js b/implementors/ndarray_linalg/triangular/trait.SolveTriangularInplace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/triangular/trait.SolveTriangularInplace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/triangular/trait.SolveTriangularInto.js b/implementors/ndarray_linalg/triangular/trait.SolveTriangularInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/triangular/trait.SolveTriangularInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/tridiagonal/trait.DeterminantTridiagonal.js b/implementors/ndarray_linalg/tridiagonal/trait.DeterminantTridiagonal.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/tridiagonal/trait.DeterminantTridiagonal.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/tridiagonal/trait.ExtractTridiagonal.js b/implementors/ndarray_linalg/tridiagonal/trait.ExtractTridiagonal.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/tridiagonal/trait.ExtractTridiagonal.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonal.js b/implementors/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonal.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonal.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonalInto.js b/implementors/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonalInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonalInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonal.js b/implementors/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonal.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonal.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonalInto.js b/implementors/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonalInto.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonalInto.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/tridiagonal/trait.SolveTridiagonal.js b/implementors/ndarray_linalg/tridiagonal/trait.SolveTridiagonal.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/tridiagonal/trait.SolveTridiagonal.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/ndarray_linalg/tridiagonal/trait.SolveTridiagonalInplace.js b/implementors/ndarray_linalg/tridiagonal/trait.SolveTridiagonalInplace.js new file mode 100644 index 00000000..2ec92135 --- /dev/null +++ b/implementors/ndarray_linalg/tridiagonal/trait.SolveTridiagonalInplace.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["ndarray_linalg"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/implementors/std/error/trait.Error.js b/implementors/std/error/trait.Error.js new file mode 100644 index 00000000..b9472b22 --- /dev/null +++ b/implementors/std/error/trait.Error.js @@ -0,0 +1,4 @@ +(function() {var implementors = {}; +implementors["lax"] = [{"text":"impl Error for Error","synthetic":false,"types":["lax::error::Error"]}]; +implementors["ndarray_linalg"] = [{"text":"impl Error for LinalgError","synthetic":false,"types":["ndarray_linalg::error::LinalgError"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/lax/CHANGELOG.md b/lax/CHANGELOG.md deleted file mode 100644 index 68e828b4..00000000 --- a/lax/CHANGELOG.md +++ /dev/null @@ -1,15 +0,0 @@ -Unreleased ------------ - -0.2.0 - 17 July 2021 -===================== - -Updated dependencies ---------------------- -- cauchy 0.4 (num-complex 0.4, rand 0.8), lapack 0.18 https://github.com/rust-ndarray/ndarray-linalg/pull/276 - -Fixed ------ -- Fix memory layout of the output of inverse of LUFactorized https://github.com/rust-ndarray/ndarray-linalg/pull/297 -- Fix Eig for column-major arrays with real elements https://github.com/rust-ndarray/ndarray-linalg/pull/298 -- Fix Solve::solve_h_* for complex inputs with standard layout https://github.com/rust-ndarray/ndarray-linalg/pull/296 diff --git a/lax/Cargo.toml b/lax/Cargo.toml deleted file mode 100644 index 8e00e8f1..00000000 --- a/lax/Cargo.toml +++ /dev/null @@ -1,62 +0,0 @@ -[package] -name = "lax" -version = "0.18.0" -authors = ["Toshiki Teramura "] -edition = "2021" - -description = "LAPACK wrapper without ndarray" -documentation = "https://docs.rs/lax/" -repository = "https://github.com/rust-ndarray/ndarray-linalg" -keywords = ["lapack", "matrix"] -license = "MIT OR Apache-2.0" -readme = "README.md" -categories = ["algorithms", "science"] - -[features] -default = [] - -netlib = ["netlib-static"] -openblas = ["openblas-static"] -intel-mkl = ["intel-mkl-static-lp64-seq"] - -netlib-static = ["netlib-src/static"] -netlib-system = ["netlib-src/system"] - -openblas-static = ["openblas-src/static"] -openblas-system = ["openblas-src/system"] - -intel-mkl-static = ["intel-mkl-src/mkl-static-lp64-seq"] # deprecated, use intel-mkl-static-lp64-seq instead -intel-mkl-system = ["intel-mkl-src/mkl-dynamic-lp64-seq"] # deprecated, use intel-mkl-dynamic-lp64-seq instead - -intel-mkl-dynamic-ilp64-iomp = ["intel-mkl-src/mkl-dynamic-ilp64-iomp"] -intel-mkl-dynamic-ilp64-seq = ["intel-mkl-src/mkl-dynamic-ilp64-seq"] -intel-mkl-dynamic-lp64-iomp = ["intel-mkl-src/mkl-dynamic-lp64-iomp"] -intel-mkl-dynamic-lp64-seq = ["intel-mkl-src/mkl-dynamic-lp64-seq"] -intel-mkl-static-ilp64-iomp = ["intel-mkl-src/mkl-static-ilp64-iomp"] -intel-mkl-static-ilp64-seq = ["intel-mkl-src/mkl-static-ilp64-seq"] -intel-mkl-static-lp64-iomp = ["intel-mkl-src/mkl-static-lp64-iomp"] -intel-mkl-static-lp64-seq = ["intel-mkl-src/mkl-static-lp64-seq"] - -[dependencies] -thiserror = "2.0.0" -cauchy = "0.4.0" -num-traits = "0.2.14" -lapack-sys = "0.15.0" -katexit = "0.1.2" - -[dependencies.intel-mkl-src] -version = "0.8.1" -default-features = false -optional = true - -[dependencies.netlib-src] -version = "0.9.0" -optional = true -features = ["cblas"] -default-features = false - -[dependencies.openblas-src] -version = "0.10.4" -optional = true -default-features = false -features = ["cblas"] diff --git a/lax/README.md b/lax/README.md deleted file mode 100644 index 9dea6b32..00000000 --- a/lax/README.md +++ /dev/null @@ -1,11 +0,0 @@ -Linear Algebra eXtension (LAX) -=============================== - -[![crates.io](https://img.shields.io/badge/crates.io-lax-blue)](https://crates.io/crates/lax) -[![docs.rs](https://docs.rs/lax/badge.svg)](https://docs.rs/lax) - -ndarray-free safe Rust wrapper for LAPACK FFI for implementing ndarray-linalg crate. -This crate responsibles for - -- Linking to LAPACK shared/static libraries -- Dispatching to LAPACK routines based on scalar types by using `Lapack` trait diff --git a/lax/all.html b/lax/all.html new file mode 100644 index 00000000..0352708b --- /dev/null +++ b/lax/all.html @@ -0,0 +1,25 @@ +List of all items in this crate + + + + + + +
+ \ No newline at end of file diff --git a/lax/cholesky/trait.Cholesky_.html b/lax/cholesky/trait.Cholesky_.html new file mode 100644 index 00000000..7b3ee51b --- /dev/null +++ b/lax/cholesky/trait.Cholesky_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.Cholesky_.html...

+ + + \ No newline at end of file diff --git a/lax/eig/trait.Eig_.html b/lax/eig/trait.Eig_.html new file mode 100644 index 00000000..218d77c9 --- /dev/null +++ b/lax/eig/trait.Eig_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.Eig_.html...

+ + + \ No newline at end of file diff --git a/lax/eigh/trait.Eigh_.html b/lax/eigh/trait.Eigh_.html new file mode 100644 index 00000000..44c09209 --- /dev/null +++ b/lax/eigh/trait.Eigh_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.Eigh_.html...

+ + + \ No newline at end of file diff --git a/lax/enum.Diag.html b/lax/enum.Diag.html new file mode 100644 index 00000000..09c52d2c --- /dev/null +++ b/lax/enum.Diag.html @@ -0,0 +1,47 @@ +Diag in lax - Rust + + + + + + +
+

Enum lax::Diag

source · []
#[repr(u8)]
+pub enum Diag {
+    Unit,
+    NonUnit,
+}

Variants

Unit

NonUnit

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/enum.EigenVectorFlag.html b/lax/enum.EigenVectorFlag.html new file mode 100644 index 00000000..a31a8354 --- /dev/null +++ b/lax/enum.EigenVectorFlag.html @@ -0,0 +1,52 @@ +EigenVectorFlag in lax - Rust + + + + + + +
#[repr(u8)]
+pub enum EigenVectorFlag {
+    Calc,
+    Not,
+}
Expand description

Flag for calculating eigenvectors or not

+

Variants

Calc

Not

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/enum.NormType.html b/lax/enum.NormType.html new file mode 100644 index 00000000..778711e6 --- /dev/null +++ b/lax/enum.NormType.html @@ -0,0 +1,49 @@ +NormType in lax - Rust + + + + + + +
#[repr(u8)]
+pub enum NormType {
+    One,
+    Infinity,
+    Frobenius,
+}

Variants

One

Infinity

Frobenius

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/enum.Transpose.html b/lax/enum.Transpose.html new file mode 100644 index 00000000..d5c49270 --- /dev/null +++ b/lax/enum.Transpose.html @@ -0,0 +1,49 @@ +Transpose in lax - Rust + + + + + + +
#[repr(u8)]
+pub enum Transpose {
+    No,
+    Transpose,
+    Hermite,
+}

Variants

No

Transpose

Hermite

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/enum.UPLO.html b/lax/enum.UPLO.html new file mode 100644 index 00000000..8561d476 --- /dev/null +++ b/lax/enum.UPLO.html @@ -0,0 +1,49 @@ +UPLO in lax - Rust + + + + + + +
+

Enum lax::UPLO

source · []
#[repr(u8)]
+pub enum UPLO {
+    Upper,
+    Lower,
+}
Expand description

Upper/Lower specification for seveal usages

+

Variants

Upper

Lower

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/enum.UVTFlag.html b/lax/enum.UVTFlag.html new file mode 100644 index 00000000..ba67df9e --- /dev/null +++ b/lax/enum.UVTFlag.html @@ -0,0 +1,55 @@ +UVTFlag in lax - Rust + + + + + + +
+

Enum lax::UVTFlag

source · []
#[repr(u8)]
+pub enum UVTFlag {
+    Full,
+    Some,
+    None,
+}
Expand description

Specifies how many of the columns of U and rows of Vᵀ are computed and returned.

+

For an input array of shape m×n, the following are computed:

+

Variants

Full

All m columns of U and all n rows of Vᵀ.

+

Some

The first min(m,n) columns of U and the first min(m,n) rows of Vᵀ.

+

None

No columns of U or rows of Vᵀ.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/error/enum.Error.html b/lax/error/enum.Error.html new file mode 100644 index 00000000..3f48ba80 --- /dev/null +++ b/lax/error/enum.Error.html @@ -0,0 +1,53 @@ +Error in lax::error - Rust + + + + + + +
+

Enum lax::error::Error

source · []
pub enum Error {
+    LapackInvalidValue {
+        return_code: i32,
+    },
+    LapackComputationalFailure {
+        return_code: i32,
+    },
+    InvalidShape,
+}

Variants

LapackInvalidValue

Fields

return_code: i32

LapackComputationalFailure

Fields

return_code: i32

InvalidShape

Strides of the array is not supported

+

Trait Implementations

Formats the value using the given formatter. Read more

+

Formats the value using the given formatter. Read more

+

The lower-level source of this error, if any. Read more

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. Read more

+
👎 Deprecated since 1.42.0:

use the Display impl or to_string()

+
👎 Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

Converts the given value to a String. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/error/index.html b/lax/error/index.html new file mode 100644 index 00000000..b57b81b6 --- /dev/null +++ b/lax/error/index.html @@ -0,0 +1,29 @@ +lax::error - Rust + + + + + + +
+ \ No newline at end of file diff --git a/lax/error/sidebar-items.js b/lax/error/sidebar-items.js new file mode 100644 index 00000000..3d06bef6 --- /dev/null +++ b/lax/error/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["Error",""]],"trait":[["AsLapackResult",""]],"type":[["Result",""]]}; \ No newline at end of file diff --git a/lax/error/trait.AsLapackResult.html b/lax/error/trait.AsLapackResult.html new file mode 100644 index 00000000..bb6cfb00 --- /dev/null +++ b/lax/error/trait.AsLapackResult.html @@ -0,0 +1,28 @@ +AsLapackResult in lax::error - Rust + + + + + + +
pub trait AsLapackResult {
+    fn as_lapack_result(self) -> Result<()>;
+}

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/error/type.Result.html b/lax/error/type.Result.html new file mode 100644 index 00000000..41a92d77 --- /dev/null +++ b/lax/error/type.Result.html @@ -0,0 +1,26 @@ +Result in lax::error - Rust + + + + + + +
+

Type Definition lax::error::Result

source · []
pub type Result<T> = Result<T, Error>;
+ \ No newline at end of file diff --git a/lax/index.html b/lax/index.html new file mode 100644 index 00000000..ec8b8a75 --- /dev/null +++ b/lax/index.html @@ -0,0 +1,78 @@ +lax - Rust + + + + + + +
+

Crate lax

source · []
Expand description

Linear Algebra eXtension (LAX)

+

ndarray-free safe Rust wrapper for LAPACK FFI

+

Linear equation, Inverse matrix, Condition number

+

As the property of $A$, several types of triangular factorization are used:

+
    +
  • LU-decomposition for general matrix +
      +
    • $PA = LU$, where $L$ is lower matrix, $U$ is upper matrix, and $P$ is permutation matrix
    • +
    +
  • +
  • Bunch-Kaufman diagonal pivoting method for nonpositive-definite Hermitian matrix +
      +
    • $A = U D U^\dagger$, where $U$ is upper matrix, +$D$ is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks.
    • +
    +
  • +
+
+ + +
matrix typeTriangler factorization (TRF)Solve (TRS)Inverse matrix (TRI)Reciprocal condition number (CON)
General (GE)lusolveinvrcond
Symmetric (SY) / Hermitian (HE)bksolvehinvh-
+

Eigenvalue Problem

+

Solve eigenvalue problem for a matrix $A$

+

$$ Av_i = \lambda_i v_i $$

+

or generalized eigenvalue problem

+

$$ Av_i = \lambda_i B v_i $$

+
+ + +
matrix typeEigenvalue (EV)Generalized Eigenvalue Problem (EG)
General (GE)eig-
Symmetric (SY) / Hermitian (HE)eigheigh_generalized
+

Singular Value Decomposition (SVD), Least square problem

+ +
matrix typeSingular Value Decomposition (SVD)SVD with divided-and-conquer (SDD)Least square problem (LSD)
General (GE)svdsvddcleast_squares
+

Modules

+

Memory layout of matrices

+

Structs

+

Represents the LU factorization of a tridiagonal matrix A as A = P*L*U.

+

Result of LeastSquares

+

Result of SVD

+

Represents a tridiagonal matrix as 3 one-dimensional vectors.

+

Enums

+

Flag for calculating eigenvectors or not

+

Upper/Lower specification for seveal usages

+

Specifies how many of the columns of U and rows of Vᵀ are computed and returned.

+

Traits

+

Wraps *geev for general matrices

+

Trait for primitive types which implements LAPACK subroutines

+

Wraps *gesvd

+

Wraps *trtri and *trtrs

+

Wraps *gttrf, *gtcon and *gttrs

+

Type Definitions

+
+ \ No newline at end of file diff --git a/lax/layout/enum.MatrixLayout.html b/lax/layout/enum.MatrixLayout.html new file mode 100644 index 00000000..30c4c349 --- /dev/null +++ b/lax/layout/enum.MatrixLayout.html @@ -0,0 +1,67 @@ +MatrixLayout in lax::layout - Rust + + + + + + +
pub enum MatrixLayout {
+    C {
+        row: i32,
+        lda: i32,
+    },
+    F {
+        col: i32,
+        lda: i32,
+    },
+}

Variants

C

Fields

row: i32
lda: i32

F

Fields

col: i32
lda: i32

Implementations

Transpose without changing memory representation

+

C-contigious row=2, lda=3

+
[[1, 2, 3]
+ [4, 5, 6]]
+

and F-contigious col=2, lda=3

+
[[1, 4]
+ [2, 5]
+ [3, 6]]
+

have same memory representation [1, 2, 3, 4, 5, 6], and this toggles them.

+ +
let layout = MatrixLayout::C { row: 2, lda: 3 };
+assert_eq!(layout.t(), MatrixLayout::F { col: 2, lda: 3 });
+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/layout/fn.square_transpose.html b/lax/layout/fn.square_transpose.html new file mode 100644 index 00000000..aaccae16 --- /dev/null +++ b/lax/layout/fn.square_transpose.html @@ -0,0 +1,43 @@ +square_transpose in lax::layout - Rust + + + + + + +
pub fn square_transpose<T: Copy>(layout: MatrixLayout, a: &mut [T])
Expand description

In-place transpose of a square matrix by keeping F/C layout

+

Transpose for C-continuous array

+ +
let layout = MatrixLayout::C { row: 2, lda: 2 };
+let mut a = vec![1., 2., 3., 4.];
+square_transpose(layout, &mut a);
+assert_eq!(a, &[1., 3., 2., 4.]);
+

Transpose for F-continuous array

+ +
let layout = MatrixLayout::F { col: 2, lda: 2 };
+let mut a = vec![1., 3., 2., 4.];
+square_transpose(layout, &mut a);
+assert_eq!(a, &[1., 2., 3., 4.]);
+

Panics

+
    +
  • If size of a and layout size mismatch
  • +
+
+ \ No newline at end of file diff --git a/lax/layout/fn.transpose.html b/lax/layout/fn.transpose.html new file mode 100644 index 00000000..f0acbab8 --- /dev/null +++ b/lax/layout/fn.transpose.html @@ -0,0 +1,43 @@ +transpose in lax::layout - Rust + + + + + + +
+

Function lax::layout::transpose

source · []
pub fn transpose<T: Copy>(
    layout: MatrixLayout,
    input: &[T]
) -> (MatrixLayout, Vec<T>)
Expand description

Out-place transpose for general matrix

+

Examples

+
let layout = MatrixLayout::C { row: 2, lda: 3 };
+let a = vec![1., 2., 3., 4., 5., 6.];
+let (l, b) = transpose(layout, &a);
+assert_eq!(l, MatrixLayout::F { col: 3, lda: 2 });
+assert_eq!(b, &[1., 4., 2., 5., 3., 6.]);
+ +
let layout = MatrixLayout::F { col: 2, lda: 3 };
+let a = vec![1., 2., 3., 4., 5., 6.];
+let (l, b) = transpose(layout, &a);
+assert_eq!(l, MatrixLayout::C { row: 3, lda: 2 });
+assert_eq!(b, &[1., 4., 2., 5., 3., 6.]);
+

Panics

+
    +
  • If input array size and layout size mismatch
  • +
+
+ \ No newline at end of file diff --git a/lax/layout/fn.transpose_over.html b/lax/layout/fn.transpose_over.html new file mode 100644 index 00000000..ca0223cc --- /dev/null +++ b/lax/layout/fn.transpose_over.html @@ -0,0 +1,45 @@ +transpose_over in lax::layout - Rust + + + + + + +
pub fn transpose_over<T: Copy>(
    layout: MatrixLayout,
    from: &[T],
    to: &mut [T]
) -> MatrixLayout
Expand description

Out-place transpose for general matrix

+

Examples

+
let layout = MatrixLayout::C { row: 2, lda: 3 };
+let a = vec![1., 2., 3., 4., 5., 6.];
+let mut b = vec![0.0; a.len()];
+let l = transpose_over(layout, &a, &mut b);
+assert_eq!(l, MatrixLayout::F { col: 3, lda: 2 });
+assert_eq!(b, &[1., 4., 2., 5., 3., 6.]);
+ +
let layout = MatrixLayout::F { col: 2, lda: 3 };
+let a = vec![1., 2., 3., 4., 5., 6.];
+let mut b = vec![0.0; a.len()];
+let l = transpose_over(layout, &a, &mut b);
+assert_eq!(l, MatrixLayout::C { row: 3, lda: 2 });
+assert_eq!(b, &[1., 4., 2., 5., 3., 6.]);
+

Panics

+
    +
  • If input array sizes and layout size mismatch
  • +
+
+ \ No newline at end of file diff --git a/lax/layout/index.html b/lax/layout/index.html new file mode 100644 index 00000000..fbfdb366 --- /dev/null +++ b/lax/layout/index.html @@ -0,0 +1,57 @@ +lax::layout - Rust + + + + + + +
+

Module lax::layout

source · []
Expand description

Memory layout of matrices

+

Different from ndarray format which consists of shape and strides, +matrix format in LAPACK consists of row or column size and leading dimension.

+

ndarray format and stride

+

Let us consider 3-dimensional array for explaining ndarray structure. +The address of (x,y,z)-element in ndarray satisfies following relation:

+
shape = [Nx, Ny, Nz]
+    where Nx > 0, Ny > 0, Nz > 0
+stride = [Sx, Sy, Sz]
+
+&data[(x, y, z)] = &data[(0, 0, 0)] + Sx*x + Sy*y + Sz*z
+    for x < Nx, y < Ny, z < Nz
+

The array is called

+
    +
  • C-continuous if [Sx, Sy, Sz] = [Nz*Ny, Nz, 1]
  • +
  • F(Fortran)-continuous if [Sx, Sy, Sz] = [1, Nx, Nx*Ny]
  • +
+

Strides of ndarray [Sx, Sy, Sz] take arbitrary value, +e.g. it can be non-ordered Sy > Sx > Sz, or can be negative Sx < 0. +If the minimum of [Sx, Sy, Sz] equals to 1, +the value of elements fills data memory region and called “continuous”. +Non-continuous ndarray is useful to get sub-array without copying data.

+

Matrix layout for LAPACK

+

LAPACK interface focuses on the linear algebra operations for F-continuous 2-dimensional array. +Under this restriction, stride becomes far simpler; we only have to consider the case [1, S] +This S for a matrix A is called “leading dimension of the array A” in LAPACK document, and denoted by lda.

+

Enums

+

Functions

+

In-place transpose of a square matrix by keeping F/C layout

+

Out-place transpose for general matrix

+

Out-place transpose for general matrix

+
+ \ No newline at end of file diff --git a/lax/layout/sidebar-items.js b/lax/layout/sidebar-items.js new file mode 100644 index 00000000..d5c22247 --- /dev/null +++ b/lax/layout/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["MatrixLayout",""]],"fn":[["square_transpose","In-place transpose of a square matrix by keeping F/C layout"],["transpose","Out-place transpose for general matrix"],["transpose_over","Out-place transpose for general matrix"]]}; \ No newline at end of file diff --git a/lax/least_squares/struct.LeastSquaresOutput.html b/lax/least_squares/struct.LeastSquaresOutput.html new file mode 100644 index 00000000..55b7f242 --- /dev/null +++ b/lax/least_squares/struct.LeastSquaresOutput.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/struct.LeastSquaresOutput.html...

+ + + \ No newline at end of file diff --git a/lax/least_squares/trait.LeastSquaresSvdDivideConquer_.html b/lax/least_squares/trait.LeastSquaresSvdDivideConquer_.html new file mode 100644 index 00000000..f22e21b4 --- /dev/null +++ b/lax/least_squares/trait.LeastSquaresSvdDivideConquer_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.LeastSquaresSvdDivideConquer_.html...

+ + + \ No newline at end of file diff --git a/lax/opnorm/trait.OperatorNorm_.html b/lax/opnorm/trait.OperatorNorm_.html new file mode 100644 index 00000000..67e3c9e1 --- /dev/null +++ b/lax/opnorm/trait.OperatorNorm_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.OperatorNorm_.html...

+ + + \ No newline at end of file diff --git a/lax/qr/trait.QR_.html b/lax/qr/trait.QR_.html new file mode 100644 index 00000000..3816fd9e --- /dev/null +++ b/lax/qr/trait.QR_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.QR_.html...

+ + + \ No newline at end of file diff --git a/lax/rcond/trait.Rcond_.html b/lax/rcond/trait.Rcond_.html new file mode 100644 index 00000000..ffaf0032 --- /dev/null +++ b/lax/rcond/trait.Rcond_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.Rcond_.html...

+ + + \ No newline at end of file diff --git a/lax/sidebar-items.js b/lax/sidebar-items.js new file mode 100644 index 00000000..2df28d13 --- /dev/null +++ b/lax/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["Diag",""],["EigenVectorFlag","Flag for calculating eigenvectors or not"],["NormType",""],["Transpose",""],["UPLO","Upper/Lower specification for seveal usages"],["UVTFlag","Specifies how many of the columns of U and rows of Vᵀ are computed and returned."]],"mod":[["error",""],["layout","Memory layout of matrices"]],"struct":[["LUFactorizedTridiagonal","Represents the LU factorization of a tridiagonal matrix `A` as `A = P*L*U`."],["LeastSquaresOutput","Result of LeastSquares"],["SVDOutput","Result of SVD"],["Tridiagonal","Represents a tridiagonal matrix as 3 one-dimensional vectors."]],"trait":[["Cholesky_",""],["Eig_","Wraps `*geev` for general matrices"],["Eigh_",""],["Lapack","Trait for primitive types which implements LAPACK subroutines"],["LeastSquaresSvdDivideConquer_","Wraps `*gelsd`"],["OperatorNorm_",""],["QR_",""],["Rcond_",""],["SVDDC_",""],["SVD_","Wraps `*gesvd`"],["Solve_",""],["Solveh_",""],["Triangular_","Wraps `*trtri` and `*trtrs`"],["Tridiagonal_","Wraps `*gttrf`, `*gtcon` and `*gttrs`"]],"type":[["Pivot",""]]}; \ No newline at end of file diff --git a/lax/solve/trait.Solve_.html b/lax/solve/trait.Solve_.html new file mode 100644 index 00000000..ebecf200 --- /dev/null +++ b/lax/solve/trait.Solve_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.Solve_.html...

+ + + \ No newline at end of file diff --git a/lax/solveh/trait.Solveh_.html b/lax/solveh/trait.Solveh_.html new file mode 100644 index 00000000..ce928e41 --- /dev/null +++ b/lax/solveh/trait.Solveh_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.Solveh_.html...

+ + + \ No newline at end of file diff --git a/lax/src/alloc.rs b/lax/src/alloc.rs deleted file mode 100644 index 63458818..00000000 --- a/lax/src/alloc.rs +++ /dev/null @@ -1,78 +0,0 @@ -use cauchy::*; -use std::mem::MaybeUninit; - -/// Helper for getting pointer of slice -pub(crate) trait AsPtr: Sized { - type Elem; - fn as_ptr(vec: &[Self]) -> *const Self::Elem; - fn as_mut_ptr(vec: &mut [Self]) -> *mut Self::Elem; -} - -macro_rules! impl_as_ptr { - ($target:ty, $elem:ty) => { - impl AsPtr for $target { - type Elem = $elem; - fn as_ptr(vec: &[Self]) -> *const Self::Elem { - vec.as_ptr() as *const _ - } - fn as_mut_ptr(vec: &mut [Self]) -> *mut Self::Elem { - vec.as_mut_ptr() as *mut _ - } - } - }; -} -impl_as_ptr!(i32, i32); -impl_as_ptr!(f32, f32); -impl_as_ptr!(f64, f64); -impl_as_ptr!(c32, lapack_sys::__BindgenComplex); -impl_as_ptr!(c64, lapack_sys::__BindgenComplex); -impl_as_ptr!(MaybeUninit, i32); -impl_as_ptr!(MaybeUninit, f32); -impl_as_ptr!(MaybeUninit, f64); -impl_as_ptr!(MaybeUninit, lapack_sys::__BindgenComplex); -impl_as_ptr!(MaybeUninit, lapack_sys::__BindgenComplex); - -pub(crate) trait VecAssumeInit { - type Elem; - unsafe fn assume_init(self) -> Vec; - - /// An replacement of unstable API - /// https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#method.slice_assume_init_ref - unsafe fn slice_assume_init_ref(&self) -> &[Self::Elem]; - - /// An replacement of unstable API - /// https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#method.slice_assume_init_mut - unsafe fn slice_assume_init_mut(&mut self) -> &mut [Self::Elem]; -} - -impl VecAssumeInit for Vec> { - type Elem = T; - unsafe fn assume_init(self) -> Vec { - // FIXME use Vec::into_raw_parts instead after stablized - // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.into_raw_parts - let mut me = std::mem::ManuallyDrop::new(self); - Vec::from_raw_parts(me.as_mut_ptr() as *mut T, me.len(), me.capacity()) - } - - unsafe fn slice_assume_init_ref(&self) -> &[T] { - std::slice::from_raw_parts(self.as_ptr() as *const T, self.len()) - } - - unsafe fn slice_assume_init_mut(&mut self) -> &mut [T] { - std::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut T, self.len()) - } -} - -/// Create a vector without initialization -/// -/// Safety -/// ------ -/// - Memory is not initialized. Do not read the memory before write. -/// -pub(crate) fn vec_uninit(n: usize) -> Vec> { - let mut v = Vec::with_capacity(n); - unsafe { - v.set_len(n); - } - v -} diff --git a/lax/src/cholesky.rs b/lax/src/cholesky.rs deleted file mode 100644 index 785f6e5e..00000000 --- a/lax/src/cholesky.rs +++ /dev/null @@ -1,142 +0,0 @@ -//! Factorize positive-definite symmetric/Hermitian matrices using Cholesky algorithm - -use super::*; -use crate::{error::*, layout::*}; -use cauchy::*; - -/// Compute Cholesky decomposition according to [UPLO] -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | spotrf | dpotrf | cpotrf | zpotrf | -/// -pub trait CholeskyImpl: Scalar { - fn cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()>; -} - -macro_rules! impl_cholesky_ { - ($s:ty, $trf:path) => { - impl CholeskyImpl for $s { - fn cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()> { - let (n, _) = l.size(); - if matches!(l, MatrixLayout::C { .. }) { - square_transpose(l, a); - } - let mut info = 0; - unsafe { - $trf(uplo.as_ptr(), &n, AsPtr::as_mut_ptr(a), &n, &mut info); - } - info.as_lapack_result()?; - if matches!(l, MatrixLayout::C { .. }) { - square_transpose(l, a); - } - Ok(()) - } - } - }; -} -impl_cholesky_!(c64, lapack_sys::zpotrf_); -impl_cholesky_!(c32, lapack_sys::cpotrf_); -impl_cholesky_!(f64, lapack_sys::dpotrf_); -impl_cholesky_!(f32, lapack_sys::spotrf_); - -/// Compute inverse matrix using Cholesky factroization result -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | spotri | dpotri | cpotri | zpotri | -/// -pub trait InvCholeskyImpl: Scalar { - fn inv_cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()>; -} - -macro_rules! impl_inv_cholesky { - ($s:ty, $tri:path) => { - impl InvCholeskyImpl for $s { - fn inv_cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()> { - let (n, _) = l.size(); - if matches!(l, MatrixLayout::C { .. }) { - square_transpose(l, a); - } - let mut info = 0; - unsafe { - $tri(uplo.as_ptr(), &n, AsPtr::as_mut_ptr(a), &l.lda(), &mut info); - } - info.as_lapack_result()?; - if matches!(l, MatrixLayout::C { .. }) { - square_transpose(l, a); - } - Ok(()) - } - } - }; -} -impl_inv_cholesky!(c64, lapack_sys::zpotri_); -impl_inv_cholesky!(c32, lapack_sys::cpotri_); -impl_inv_cholesky!(f64, lapack_sys::dpotri_); -impl_inv_cholesky!(f32, lapack_sys::spotri_); - -/// Solve linear equation using Cholesky factroization result -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | spotrs | dpotrs | cpotrs | zpotrs | -/// -pub trait SolveCholeskyImpl: Scalar { - fn solve_cholesky(l: MatrixLayout, uplo: UPLO, a: &[Self], b: &mut [Self]) -> Result<()>; -} - -macro_rules! impl_solve_cholesky { - ($s:ty, $trs:path) => { - impl SolveCholeskyImpl for $s { - fn solve_cholesky( - l: MatrixLayout, - mut uplo: UPLO, - a: &[Self], - b: &mut [Self], - ) -> Result<()> { - let (n, _) = l.size(); - let nrhs = 1; - let mut info = 0; - if matches!(l, MatrixLayout::C { .. }) { - uplo = uplo.t(); - for val in b.iter_mut() { - *val = val.conj(); - } - } - unsafe { - $trs( - uplo.as_ptr(), - &n, - &nrhs, - AsPtr::as_ptr(a), - &l.lda(), - AsPtr::as_mut_ptr(b), - &n, - &mut info, - ); - } - info.as_lapack_result()?; - if matches!(l, MatrixLayout::C { .. }) { - for val in b.iter_mut() { - *val = val.conj(); - } - } - Ok(()) - } - } - }; -} -impl_solve_cholesky!(c64, lapack_sys::zpotrs_); -impl_solve_cholesky!(c32, lapack_sys::cpotrs_); -impl_solve_cholesky!(f64, lapack_sys::dpotrs_); -impl_solve_cholesky!(f32, lapack_sys::spotrs_); diff --git a/lax/src/eig.rs b/lax/src/eig.rs deleted file mode 100644 index f02035bb..00000000 --- a/lax/src/eig.rs +++ /dev/null @@ -1,451 +0,0 @@ -//! Eigenvalue problem for general matricies -//! -//! LAPACK correspondance -//! ---------------------- -//! -//! | f32 | f64 | c32 | c64 | -//! |:------|:------|:------|:------| -//! | sgeev | dgeev | cgeev | zgeev | -//! - -use crate::{error::*, layout::MatrixLayout, *}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -#[cfg_attr(doc, katexit::katexit)] -/// Eigenvalue problem for general matrix -/// -/// To manage memory more strictly, use [EigWork]. -/// -/// Right and Left eigenvalue problem -/// ---------------------------------- -/// LAPACK can solve both right eigenvalue problem -/// $$ -/// AV_R = V_R \Lambda -/// $$ -/// where $V_R = \left( v_R^1, \cdots, v_R^n \right)$ are right eigenvectors -/// and left eigenvalue problem -/// $$ -/// V_L^\dagger A = V_L^\dagger \Lambda -/// $$ -/// where $V_L = \left( v_L^1, \cdots, v_L^n \right)$ are left eigenvectors -/// and eigenvalues -/// $$ -/// \Lambda = \begin{pmatrix} -/// \lambda_1 & & 0 \\\\ -/// & \ddots & \\\\ -/// 0 & & \lambda_n -/// \end{pmatrix} -/// $$ -/// which satisfies $A v_R^i = \lambda_i v_R^i$ and -/// $\left(v_L^i\right)^\dagger A = \lambda_i \left(v_L^i\right)^\dagger$ -/// for column-major matrices, although row-major matrices are not supported. -/// Since a row-major matrix can be interpreted -/// as a transpose of a column-major matrix, -/// this transforms right eigenvalue problem to left one: -/// -/// $$ -/// A^\dagger V = V Λ ⟺ V^\dagger A = Λ V^\dagger -/// $$ -/// -#[non_exhaustive] -pub struct EigWork { - /// Problem size - pub n: i32, - /// Compute right eigenvectors or not - pub jobvr: JobEv, - /// Compute left eigenvectors or not - pub jobvl: JobEv, - - /// Eigenvalues - pub eigs: Vec>, - /// Real part of eigenvalues used in real routines - pub eigs_re: Option>>, - /// Imaginary part of eigenvalues used in real routines - pub eigs_im: Option>>, - - /// Left eigenvectors - pub vc_l: Option>>, - /// Left eigenvectors used in real routines - pub vr_l: Option>>, - /// Right eigenvectors - pub vc_r: Option>>, - /// Right eigenvectors used in real routines - pub vr_r: Option>>, - - /// Working memory - pub work: Vec>, - /// Working memory with `T::Real` - pub rwork: Option>>, -} - -impl EigWork -where - T: Scalar, - EigWork: EigWorkImpl, -{ - /// Create new working memory for eigenvalues compution. - pub fn new(calc_v: bool, l: MatrixLayout) -> Result { - EigWorkImpl::new(calc_v, l) - } - - /// Compute eigenvalues and vectors on this working memory. - pub fn calc(&mut self, a: &mut [T]) -> Result> { - EigWorkImpl::calc(self, a) - } - - /// Compute eigenvalues and vectors by consuming this working memory. - pub fn eval(self, a: &mut [T]) -> Result> { - EigWorkImpl::eval(self, a) - } -} - -/// Owned result of eigenvalue problem by [EigWork::eval] -#[derive(Debug, Clone, PartialEq)] -pub struct EigOwned { - /// Eigenvalues - pub eigs: Vec, - /// Right eigenvectors - pub vr: Option>, - /// Left eigenvectors - pub vl: Option>, -} - -/// Reference result of eigenvalue problem by [EigWork::calc] -#[derive(Debug, Clone, PartialEq)] -pub struct EigRef<'work, T: Scalar> { - /// Eigenvalues - pub eigs: &'work [T::Complex], - /// Right eigenvectors - pub vr: Option<&'work [T::Complex]>, - /// Left eigenvectors - pub vl: Option<&'work [T::Complex]>, -} - -/// Helper trait for implementing [EigWork] methods -pub trait EigWorkImpl: Sized { - type Elem: Scalar; - fn new(calc_v: bool, l: MatrixLayout) -> Result; - fn calc<'work>(&'work mut self, a: &mut [Self::Elem]) -> Result>; - fn eval(self, a: &mut [Self::Elem]) -> Result>; -} - -macro_rules! impl_eig_work_c { - ($c:ty, $ev:path) => { - impl EigWorkImpl for EigWork<$c> { - type Elem = $c; - - fn new(calc_v: bool, l: MatrixLayout) -> Result { - let (n, _) = l.size(); - let (jobvl, jobvr) = if calc_v { - match l { - MatrixLayout::C { .. } => (JobEv::All, JobEv::None), - MatrixLayout::F { .. } => (JobEv::None, JobEv::All), - } - } else { - (JobEv::None, JobEv::None) - }; - let mut eigs = vec_uninit(n as usize); - let mut rwork = vec_uninit(2 * n as usize); - - let mut vc_l = jobvl.then(|| vec_uninit((n * n) as usize)); - let mut vc_r = jobvr.then(|| vec_uninit((n * n) as usize)); - - // calc work size - let mut info = 0; - let mut work_size = [<$c>::zero()]; - unsafe { - $ev( - jobvl.as_ptr(), - jobvr.as_ptr(), - &n, - std::ptr::null_mut(), - &n, - AsPtr::as_mut_ptr(&mut eigs), - AsPtr::as_mut_ptr(vc_l.as_deref_mut().unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(vc_r.as_deref_mut().unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - AsPtr::as_mut_ptr(&mut rwork), - &mut info, - ) - }; - info.as_lapack_result()?; - - let lwork = work_size[0].to_usize().unwrap(); - let work: Vec> = vec_uninit(lwork); - Ok(Self { - n, - jobvl, - jobvr, - eigs, - eigs_re: None, - eigs_im: None, - rwork: Some(rwork), - vc_l, - vc_r, - vr_l: None, - vr_r: None, - work, - }) - } - - fn calc<'work>( - &'work mut self, - a: &mut [Self::Elem], - ) -> Result> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $ev( - self.jobvl.as_ptr(), - self.jobvr.as_ptr(), - &self.n, - AsPtr::as_mut_ptr(a), - &self.n, - AsPtr::as_mut_ptr(&mut self.eigs), - AsPtr::as_mut_ptr(self.vc_l.as_deref_mut().unwrap_or(&mut [])), - &self.n, - AsPtr::as_mut_ptr(self.vc_r.as_deref_mut().unwrap_or(&mut [])), - &self.n, - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - AsPtr::as_mut_ptr(self.rwork.as_mut().unwrap()), - &mut info, - ) - }; - info.as_lapack_result()?; - // Hermite conjugate - if let Some(vl) = self.vc_l.as_mut() { - for value in vl { - let value = unsafe { value.assume_init_mut() }; - value.im = -value.im; - } - } - Ok(EigRef { - eigs: unsafe { self.eigs.slice_assume_init_ref() }, - vl: self - .vc_l - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }), - vr: self - .vc_r - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }), - }) - } - - fn eval(mut self, a: &mut [Self::Elem]) -> Result> { - let _eig_ref = self.calc(a)?; - Ok(EigOwned { - eigs: unsafe { self.eigs.assume_init() }, - vl: self.vc_l.map(|v| unsafe { v.assume_init() }), - vr: self.vc_r.map(|v| unsafe { v.assume_init() }), - }) - } - } - }; -} - -impl_eig_work_c!(c32, lapack_sys::cgeev_); -impl_eig_work_c!(c64, lapack_sys::zgeev_); - -macro_rules! impl_eig_work_r { - ($f:ty, $ev:path) => { - impl EigWorkImpl for EigWork<$f> { - type Elem = $f; - - fn new(calc_v: bool, l: MatrixLayout) -> Result { - let (n, _) = l.size(); - let (jobvl, jobvr) = if calc_v { - match l { - MatrixLayout::C { .. } => (JobEv::All, JobEv::None), - MatrixLayout::F { .. } => (JobEv::None, JobEv::All), - } - } else { - (JobEv::None, JobEv::None) - }; - let mut eigs_re = vec_uninit(n as usize); - let mut eigs_im = vec_uninit(n as usize); - let mut vr_l = jobvl.then(|| vec_uninit((n * n) as usize)); - let mut vr_r = jobvr.then(|| vec_uninit((n * n) as usize)); - let vc_l = jobvl.then(|| vec_uninit((n * n) as usize)); - let vc_r = jobvr.then(|| vec_uninit((n * n) as usize)); - - // calc work size - let mut info = 0; - let mut work_size: [$f; 1] = [0.0]; - unsafe { - $ev( - jobvl.as_ptr(), - jobvr.as_ptr(), - &n, - std::ptr::null_mut(), - &n, - AsPtr::as_mut_ptr(&mut eigs_re), - AsPtr::as_mut_ptr(&mut eigs_im), - AsPtr::as_mut_ptr(vr_l.as_deref_mut().unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(vr_r.as_deref_mut().unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ) - }; - info.as_lapack_result()?; - - // actual ev - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - - Ok(Self { - n, - jobvr, - jobvl, - eigs: vec_uninit(n as usize), - eigs_re: Some(eigs_re), - eigs_im: Some(eigs_im), - rwork: None, - vr_l, - vr_r, - vc_l, - vc_r, - work, - }) - } - - fn calc<'work>( - &'work mut self, - a: &mut [Self::Elem], - ) -> Result> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $ev( - self.jobvl.as_ptr(), - self.jobvr.as_ptr(), - &self.n, - AsPtr::as_mut_ptr(a), - &self.n, - AsPtr::as_mut_ptr(self.eigs_re.as_mut().unwrap()), - AsPtr::as_mut_ptr(self.eigs_im.as_mut().unwrap()), - AsPtr::as_mut_ptr(self.vr_l.as_deref_mut().unwrap_or(&mut [])), - &self.n, - AsPtr::as_mut_ptr(self.vr_r.as_deref_mut().unwrap_or(&mut [])), - &self.n, - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ) - }; - info.as_lapack_result()?; - - let eigs_re = self - .eigs_re - .as_ref() - .map(|e| unsafe { e.slice_assume_init_ref() }) - .unwrap(); - let eigs_im = self - .eigs_im - .as_ref() - .map(|e| unsafe { e.slice_assume_init_ref() }) - .unwrap(); - reconstruct_eigs(eigs_re, eigs_im, &mut self.eigs); - - if let Some(v) = self.vr_l.as_ref() { - let v = unsafe { v.slice_assume_init_ref() }; - reconstruct_eigenvectors(true, eigs_im, v, self.vc_l.as_mut().unwrap()); - } - if let Some(v) = self.vr_r.as_ref() { - let v = unsafe { v.slice_assume_init_ref() }; - reconstruct_eigenvectors(false, eigs_im, v, self.vc_r.as_mut().unwrap()); - } - - Ok(EigRef { - eigs: unsafe { self.eigs.slice_assume_init_ref() }, - vl: self - .vc_l - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }), - vr: self - .vc_r - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }), - }) - } - - fn eval(mut self, a: &mut [Self::Elem]) -> Result> { - let _eig_ref = self.calc(a)?; - Ok(EigOwned { - eigs: unsafe { self.eigs.assume_init() }, - vl: self.vc_l.map(|v| unsafe { v.assume_init() }), - vr: self.vc_r.map(|v| unsafe { v.assume_init() }), - }) - } - } - }; -} -impl_eig_work_r!(f32, lapack_sys::sgeev_); -impl_eig_work_r!(f64, lapack_sys::dgeev_); - -/// Reconstruct eigenvectors into complex-array -/// -/// From LAPACK API https://software.intel.com/en-us/node/469230 -/// -/// - If the j-th eigenvalue is real, -/// - v(j) = VR(:,j), the j-th column of VR. -/// -/// - If the j-th and (j+1)-st eigenvalues form a complex conjugate pair, -/// - v(j) = VR(:,j) + i*VR(:,j+1) -/// - v(j+1) = VR(:,j) - i*VR(:,j+1). -/// -/// In the C-layout case, we need the conjugates of the left -/// eigenvectors, so the signs should be reversed. -pub(crate) fn reconstruct_eigenvectors( - take_hermite_conjugate: bool, - eig_im: &[T], - vr: &[T], - vc: &mut [MaybeUninit], -) { - let n = eig_im.len(); - assert_eq!(vr.len(), n * n); - assert_eq!(vc.len(), n * n); - - let mut col = 0; - while col < n { - if eig_im[col].is_zero() { - // The corresponding eigenvalue is real. - for row in 0..n { - let re = vr[row + col * n]; - vc[row + col * n].write(T::complex(re, T::zero())); - } - col += 1; - } else { - // This is a complex conjugate pair. - assert!(col + 1 < n); - for row in 0..n { - let re = vr[row + col * n]; - let mut im = vr[row + (col + 1) * n]; - if take_hermite_conjugate { - im = -im; - } - vc[row + col * n].write(T::complex(re, im)); - vc[row + (col + 1) * n].write(T::complex(re, -im)); - } - col += 2; - } - } -} - -/// Create complex eigenvalues from real and imaginary parts. -fn reconstruct_eigs(re: &[T], im: &[T], eigs: &mut [MaybeUninit]) { - let n = eigs.len(); - assert_eq!(re.len(), n); - assert_eq!(im.len(), n); - for i in 0..n { - eigs[i].write(T::complex(re[i], im[i])); - } -} diff --git a/lax/src/eig_generalized.rs b/lax/src/eig_generalized.rs deleted file mode 100644 index ea99dbdb..00000000 --- a/lax/src/eig_generalized.rs +++ /dev/null @@ -1,520 +0,0 @@ -//! Generalized eigenvalue problem for general matrices -//! -//! LAPACK correspondance -//! ---------------------- -//! -//! | f32 | f64 | c32 | c64 | -//! |:------|:------|:------|:------| -//! | sggev | dggev | cggev | zggev | -//! -use std::mem::MaybeUninit; - -use crate::eig::reconstruct_eigenvectors; -use crate::{error::*, layout::MatrixLayout, *}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -#[derive(Clone, PartialEq, Eq)] -pub enum GeneralizedEigenvalue { - /// Finite generalized eigenvalue: `Finite(α/β, (α, β))` - Finite(T, (T, T)), - - /// Indeterminate generalized eigenvalue: `Indeterminate((α, β))` - Indeterminate((T, T)), -} - -impl std::fmt::Display for GeneralizedEigenvalue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Finite(e, (a, b)) => write!(f, "{e:.3e} ({a:.3e}/{b:.3e})"), - Self::Indeterminate((a, b)) => write!(f, "∞ ({a:.3e}/{b:.3e})"), - } - } -} - -#[non_exhaustive] -pub struct EigGeneralizedWork { - /// Problem size - pub n: i32, - /// Compute right eigenvectors or not - pub jobvr: JobEv, - /// Compute left eigenvectors or not - pub jobvl: JobEv, - - /// Eigenvalues: alpha (numerators) - pub alpha: Vec>, - /// Eigenvalues: beta (denominators) - pub beta: Vec>, - /// Real part of alpha (eigenvalue numerators) used in real routines - pub alpha_re: Option>>, - /// Imaginary part of alpha (eigenvalue numerators) used in real routines - pub alpha_im: Option>>, - /// Real part of beta (eigenvalue denominators) used in real routines - pub beta_re: Option>>, - /// Imaginary part of beta (eigenvalue denominators) used in real routines - pub beta_im: Option>>, - - /// Left eigenvectors - pub vc_l: Option>>, - /// Left eigenvectors used in real routines - pub vr_l: Option>>, - /// Right eigenvectors - pub vc_r: Option>>, - /// Right eigenvectors used in real routines - pub vr_r: Option>>, - - /// Working memory - pub work: Vec>, - /// Working memory with `T::Real` - pub rwork: Option>>, -} - -impl EigGeneralizedWork -where - T: Scalar, - EigGeneralizedWork: EigGeneralizedWorkImpl, -{ - /// Create new working memory for eigenvalues compution. - pub fn new(calc_v: bool, l: MatrixLayout) -> Result { - EigGeneralizedWorkImpl::new(calc_v, l) - } - - /// Compute eigenvalues and vectors on this working memory. - pub fn calc(&mut self, a: &mut [T], b: &mut [T]) -> Result> { - EigGeneralizedWorkImpl::calc(self, a, b) - } - - /// Compute eigenvalues and vectors by consuming this working memory. - pub fn eval(self, a: &mut [T], b: &mut [T]) -> Result> { - EigGeneralizedWorkImpl::eval(self, a, b) - } -} - -/// Owned result of eigenvalue problem by [EigGeneralizedWork::eval] -#[derive(Debug, Clone, PartialEq)] -pub struct EigGeneralizedOwned { - /// Eigenvalues - pub alpha: Vec, - - pub beta: Vec, - - /// Right eigenvectors - pub vr: Option>, - - /// Left eigenvectors - pub vl: Option>, -} - -/// Reference result of eigenvalue problem by [EigGeneralizedWork::calc] -#[derive(Debug, Clone, PartialEq)] -pub struct EigGeneralizedRef<'work, T: Scalar> { - /// Eigenvalues - pub alpha: &'work [T::Complex], - - pub beta: &'work [T::Complex], - - /// Right eigenvectors - pub vr: Option<&'work [T::Complex]>, - - /// Left eigenvectors - pub vl: Option<&'work [T::Complex]>, -} - -/// Helper trait for implementing [EigGeneralizedWork] methods -pub trait EigGeneralizedWorkImpl: Sized { - type Elem: Scalar; - fn new(calc_v: bool, l: MatrixLayout) -> Result; - fn calc<'work>( - &'work mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result>; - fn eval( - self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result>; -} - -macro_rules! impl_eig_generalized_work_c { - ($f:ty, $c:ty, $ev:path) => { - impl EigGeneralizedWorkImpl for EigGeneralizedWork<$c> { - type Elem = $c; - - fn new(calc_v: bool, l: MatrixLayout) -> Result { - let (n, _) = l.size(); - let (jobvl, jobvr) = if calc_v { - match l { - MatrixLayout::C { .. } => (JobEv::All, JobEv::None), - MatrixLayout::F { .. } => (JobEv::None, JobEv::All), - } - } else { - (JobEv::None, JobEv::None) - }; - let mut rwork = vec_uninit(8 * n as usize); - - let mut alpha = vec_uninit(n as usize); - let mut beta = vec_uninit(n as usize); - - let mut vc_l = jobvl.then(|| vec_uninit((n * n) as usize)); - let mut vc_r = jobvr.then(|| vec_uninit((n * n) as usize)); - - // calc work size - let mut info = 0; - let mut work_size = [<$c>::zero()]; - unsafe { - $ev( - jobvl.as_ptr(), - jobvr.as_ptr(), - &n, - std::ptr::null_mut(), - &n, - std::ptr::null_mut(), - &n, - AsPtr::as_mut_ptr(&mut alpha), - AsPtr::as_mut_ptr(&mut beta), - AsPtr::as_mut_ptr(vc_l.as_deref_mut().unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(vc_r.as_deref_mut().unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - AsPtr::as_mut_ptr(&mut rwork), - &mut info, - ) - }; - info.as_lapack_result()?; - - let lwork = work_size[0].to_usize().unwrap(); - let work: Vec> = vec_uninit(lwork); - Ok(Self { - n, - jobvl, - jobvr, - alpha, - beta, - alpha_re: None, - alpha_im: None, - beta_re: None, - beta_im: None, - rwork: Some(rwork), - vc_l, - vc_r, - vr_l: None, - vr_r: None, - work, - }) - } - - fn calc<'work>( - &'work mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $ev( - self.jobvl.as_ptr(), - self.jobvr.as_ptr(), - &self.n, - AsPtr::as_mut_ptr(a), - &self.n, - AsPtr::as_mut_ptr(b), - &self.n, - AsPtr::as_mut_ptr(&mut self.alpha), - AsPtr::as_mut_ptr(&mut self.beta), - AsPtr::as_mut_ptr(self.vc_l.as_deref_mut().unwrap_or(&mut [])), - &self.n, - AsPtr::as_mut_ptr(self.vc_r.as_deref_mut().unwrap_or(&mut [])), - &self.n, - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - AsPtr::as_mut_ptr(self.rwork.as_mut().unwrap()), - &mut info, - ) - }; - info.as_lapack_result()?; - // Hermite conjugate - if let Some(vl) = self.vc_l.as_mut() { - for value in vl { - let value = unsafe { value.assume_init_mut() }; - value.im = -value.im; - } - } - Ok(EigGeneralizedRef { - alpha: unsafe { self.alpha.slice_assume_init_ref() }, - beta: unsafe { self.beta.slice_assume_init_ref() }, - vl: self - .vc_l - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }), - vr: self - .vc_r - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }), - }) - } - - fn eval( - mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result> { - let _eig_generalized_ref = self.calc(a, b)?; - Ok(EigGeneralizedOwned { - alpha: unsafe { self.alpha.assume_init() }, - beta: unsafe { self.beta.assume_init() }, - vl: self.vc_l.map(|v| unsafe { v.assume_init() }), - vr: self.vc_r.map(|v| unsafe { v.assume_init() }), - }) - } - } - - impl EigGeneralizedOwned<$c> { - pub fn calc_eigs(&self, thresh_opt: Option<$f>) -> Vec> { - self.alpha - .iter() - .zip(self.beta.iter()) - .map(|(alpha, beta)| { - if let Some(thresh) = thresh_opt { - if beta.abs() < thresh { - GeneralizedEigenvalue::Indeterminate((alpha.clone(), beta.clone())) - } else { - GeneralizedEigenvalue::Finite( - alpha / beta, - (alpha.clone(), beta.clone()), - ) - } - } else { - if beta.is_zero() { - GeneralizedEigenvalue::Indeterminate((alpha.clone(), beta.clone())) - } else { - GeneralizedEigenvalue::Finite( - alpha / beta, - (alpha.clone(), beta.clone()), - ) - } - } - }) - .collect::>() - } - } - }; -} - -impl_eig_generalized_work_c!(f32, c32, lapack_sys::cggev_); -impl_eig_generalized_work_c!(f64, c64, lapack_sys::zggev_); - -macro_rules! impl_eig_generalized_work_r { - ($f:ty, $c:ty, $ev:path) => { - impl EigGeneralizedWorkImpl for EigGeneralizedWork<$f> { - type Elem = $f; - - fn new(calc_v: bool, l: MatrixLayout) -> Result { - let (n, _) = l.size(); - let (jobvl, jobvr) = if calc_v { - match l { - MatrixLayout::C { .. } => (JobEv::All, JobEv::None), - MatrixLayout::F { .. } => (JobEv::None, JobEv::All), - } - } else { - (JobEv::None, JobEv::None) - }; - let mut alpha_re = vec_uninit(n as usize); - let mut alpha_im = vec_uninit(n as usize); - let mut beta_re = vec_uninit(n as usize); - let mut vr_l = jobvl.then(|| vec_uninit((n * n) as usize)); - let mut vr_r = jobvr.then(|| vec_uninit((n * n) as usize)); - let vc_l = jobvl.then(|| vec_uninit((n * n) as usize)); - let vc_r = jobvr.then(|| vec_uninit((n * n) as usize)); - - // calc work size - let mut info = 0; - let mut work_size: [$f; 1] = [0.0]; - unsafe { - $ev( - jobvl.as_ptr(), - jobvr.as_ptr(), - &n, - std::ptr::null_mut(), - &n, - std::ptr::null_mut(), - &n, - AsPtr::as_mut_ptr(&mut alpha_re), - AsPtr::as_mut_ptr(&mut alpha_im), - AsPtr::as_mut_ptr(&mut beta_re), - AsPtr::as_mut_ptr(vr_l.as_deref_mut().unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(vr_r.as_deref_mut().unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ) - }; - info.as_lapack_result()?; - - // actual ev - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - - Ok(Self { - n, - jobvr, - jobvl, - alpha: vec_uninit(n as usize), - beta: vec_uninit(n as usize), - alpha_re: Some(alpha_re), - alpha_im: Some(alpha_im), - beta_re: Some(beta_re), - beta_im: None, - rwork: None, - vr_l, - vr_r, - vc_l, - vc_r, - work, - }) - } - - fn calc<'work>( - &'work mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $ev( - self.jobvl.as_ptr(), - self.jobvr.as_ptr(), - &self.n, - AsPtr::as_mut_ptr(a), - &self.n, - AsPtr::as_mut_ptr(b), - &self.n, - AsPtr::as_mut_ptr(self.alpha_re.as_mut().unwrap()), - AsPtr::as_mut_ptr(self.alpha_im.as_mut().unwrap()), - AsPtr::as_mut_ptr(self.beta_re.as_mut().unwrap()), - AsPtr::as_mut_ptr(self.vr_l.as_deref_mut().unwrap_or(&mut [])), - &self.n, - AsPtr::as_mut_ptr(self.vr_r.as_deref_mut().unwrap_or(&mut [])), - &self.n, - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ) - }; - info.as_lapack_result()?; - - let alpha_re = self - .alpha_re - .as_ref() - .map(|e| unsafe { e.slice_assume_init_ref() }) - .unwrap(); - let alpha_im = self - .alpha_im - .as_ref() - .map(|e| unsafe { e.slice_assume_init_ref() }) - .unwrap(); - let beta_re = self - .beta_re - .as_ref() - .map(|e| unsafe { e.slice_assume_init_ref() }) - .unwrap(); - reconstruct_eigs_optional_im(alpha_re, Some(alpha_im), &mut self.alpha); - reconstruct_eigs_optional_im(beta_re, None, &mut self.beta); - - if let Some(v) = self.vr_l.as_ref() { - let v = unsafe { v.slice_assume_init_ref() }; - reconstruct_eigenvectors(true, alpha_im, v, self.vc_l.as_mut().unwrap()); - } - if let Some(v) = self.vr_r.as_ref() { - let v = unsafe { v.slice_assume_init_ref() }; - reconstruct_eigenvectors(false, alpha_im, v, self.vc_r.as_mut().unwrap()); - } - - Ok(EigGeneralizedRef { - alpha: unsafe { self.alpha.slice_assume_init_ref() }, - beta: unsafe { self.beta.slice_assume_init_ref() }, - vl: self - .vc_l - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }), - vr: self - .vc_r - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }), - }) - } - - fn eval( - mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result> { - let _eig_generalized_ref = self.calc(a, b)?; - Ok(EigGeneralizedOwned { - alpha: unsafe { self.alpha.assume_init() }, - beta: unsafe { self.beta.assume_init() }, - vl: self.vc_l.map(|v| unsafe { v.assume_init() }), - vr: self.vc_r.map(|v| unsafe { v.assume_init() }), - }) - } - } - - impl EigGeneralizedOwned<$f> { - pub fn calc_eigs(&self, thresh_opt: Option<$f>) -> Vec> { - self.alpha - .iter() - .zip(self.beta.iter()) - .map(|(alpha, beta)| { - if let Some(thresh) = thresh_opt { - if beta.abs() < thresh { - GeneralizedEigenvalue::Indeterminate((alpha.clone(), beta.clone())) - } else { - GeneralizedEigenvalue::Finite( - alpha / beta, - (alpha.clone(), beta.clone()), - ) - } - } else { - if beta.is_zero() { - GeneralizedEigenvalue::Indeterminate((alpha.clone(), beta.clone())) - } else { - GeneralizedEigenvalue::Finite( - alpha / beta, - (alpha.clone(), beta.clone()), - ) - } - } - }) - .collect::>() - } - } - }; -} -impl_eig_generalized_work_r!(f32, c32, lapack_sys::sggev_); -impl_eig_generalized_work_r!(f64, c64, lapack_sys::dggev_); - -/// Create complex eigenvalues from real and optional imaginary parts. -fn reconstruct_eigs_optional_im( - re: &[T], - im_opt: Option<&[T]>, - eigs: &mut [MaybeUninit], -) { - let n = eigs.len(); - assert_eq!(re.len(), n); - - if let Some(im) = im_opt { - assert_eq!(im.len(), n); - for i in 0..n { - eigs[i].write(T::complex(re[i], im[i])); - } - } else { - for i in 0..n { - eigs[i].write(T::complex(re[i], T::zero())); - } - } -} diff --git a/lax/src/eigh.rs b/lax/src/eigh.rs deleted file mode 100644 index bb3ca500..00000000 --- a/lax/src/eigh.rs +++ /dev/null @@ -1,190 +0,0 @@ -//! Eigenvalue problem for symmetric/Hermitian matricies -//! -//! LAPACK correspondance -//! ---------------------- -//! -//! | f32 | f64 | c32 | c64 | -//! |:------|:------|:------|:------| -//! | ssyev | dsyev | cheev | zheev | - -use super::*; -use crate::{error::*, layout::MatrixLayout}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -pub struct EighWork { - pub n: i32, - pub jobz: JobEv, - pub eigs: Vec>, - pub work: Vec>, - pub rwork: Option>>, -} - -pub trait EighWorkImpl: Sized { - type Elem: Scalar; - fn new(calc_eigenvectors: bool, layout: MatrixLayout) -> Result; - fn calc(&mut self, uplo: UPLO, a: &mut [Self::Elem]) - -> Result<&[::Real]>; - fn eval(self, uplo: UPLO, a: &mut [Self::Elem]) -> Result::Real>>; -} - -macro_rules! impl_eigh_work_c { - ($c:ty, $ev:path) => { - impl EighWorkImpl for EighWork<$c> { - type Elem = $c; - - fn new(calc_eigenvectors: bool, layout: MatrixLayout) -> Result { - assert_eq!(layout.len(), layout.lda()); - let n = layout.len(); - let jobz = if calc_eigenvectors { - JobEv::All - } else { - JobEv::None - }; - let mut eigs = vec_uninit(n as usize); - let mut rwork = vec_uninit(3 * n as usize - 2 as usize); - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $ev( - jobz.as_ptr(), - UPLO::Upper.as_ptr(), // dummy, working memory is not affected by UPLO - &n, - std::ptr::null_mut(), - &n, - AsPtr::as_mut_ptr(&mut eigs), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - AsPtr::as_mut_ptr(&mut rwork), - &mut info, - ); - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(EighWork { - n, - eigs, - jobz, - work, - rwork: Some(rwork), - }) - } - - fn calc( - &mut self, - uplo: UPLO, - a: &mut [Self::Elem], - ) -> Result<&[::Real]> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $ev( - self.jobz.as_ptr(), - uplo.as_ptr(), - &self.n, - AsPtr::as_mut_ptr(a), - &self.n, - AsPtr::as_mut_ptr(&mut self.eigs), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - AsPtr::as_mut_ptr(self.rwork.as_mut().unwrap()), - &mut info, - ); - } - info.as_lapack_result()?; - Ok(unsafe { self.eigs.slice_assume_init_ref() }) - } - - fn eval( - mut self, - uplo: UPLO, - a: &mut [Self::Elem], - ) -> Result::Real>> { - let _eig = self.calc(uplo, a)?; - Ok(unsafe { self.eigs.assume_init() }) - } - } - }; -} -impl_eigh_work_c!(c64, lapack_sys::zheev_); -impl_eigh_work_c!(c32, lapack_sys::cheev_); - -macro_rules! impl_eigh_work_r { - ($f:ty, $ev:path) => { - impl EighWorkImpl for EighWork<$f> { - type Elem = $f; - - fn new(calc_eigenvectors: bool, layout: MatrixLayout) -> Result { - assert_eq!(layout.len(), layout.lda()); - let n = layout.len(); - let jobz = if calc_eigenvectors { - JobEv::All - } else { - JobEv::None - }; - let mut eigs = vec_uninit(n as usize); - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $ev( - jobz.as_ptr(), - UPLO::Upper.as_ptr(), // dummy, working memory is not affected by UPLO - &n, - std::ptr::null_mut(), - &n, - AsPtr::as_mut_ptr(&mut eigs), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ); - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(EighWork { - n, - eigs, - jobz, - work, - rwork: None, - }) - } - - fn calc( - &mut self, - uplo: UPLO, - a: &mut [Self::Elem], - ) -> Result<&[::Real]> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $ev( - self.jobz.as_ptr(), - uplo.as_ptr(), - &self.n, - AsPtr::as_mut_ptr(a), - &self.n, - AsPtr::as_mut_ptr(&mut self.eigs), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ); - } - info.as_lapack_result()?; - Ok(unsafe { self.eigs.slice_assume_init_ref() }) - } - - fn eval( - mut self, - uplo: UPLO, - a: &mut [Self::Elem], - ) -> Result::Real>> { - let _eig = self.calc(uplo, a)?; - Ok(unsafe { self.eigs.assume_init() }) - } - } - }; -} -impl_eigh_work_r!(f64, lapack_sys::dsyev_); -impl_eigh_work_r!(f32, lapack_sys::ssyev_); diff --git a/lax/src/eigh_generalized.rs b/lax/src/eigh_generalized.rs deleted file mode 100644 index 5d4d83ca..00000000 --- a/lax/src/eigh_generalized.rs +++ /dev/null @@ -1,216 +0,0 @@ -//! Generalized eigenvalue problem for symmetric/Hermitian matrices -//! -//! LAPACK correspondance -//! ---------------------- -//! -//! | f32 | f64 | c32 | c64 | -//! |:------|:------|:------|:------| -//! | ssygv | dsygv | chegv | zhegv | -//! - -use super::*; -use crate::{error::*, layout::MatrixLayout}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -pub struct EighGeneralizedWork { - pub n: i32, - pub jobz: JobEv, - pub eigs: Vec>, - pub work: Vec>, - pub rwork: Option>>, -} - -pub trait EighGeneralizedWorkImpl: Sized { - type Elem: Scalar; - fn new(calc_eigenvectors: bool, layout: MatrixLayout) -> Result; - fn calc( - &mut self, - uplo: UPLO, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result<&[::Real]>; - fn eval( - self, - uplo: UPLO, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result::Real>>; -} - -macro_rules! impl_eigh_generalized_work_c { - ($c:ty, $gv:path) => { - impl EighGeneralizedWorkImpl for EighGeneralizedWork<$c> { - type Elem = $c; - - fn new(calc_eigenvectors: bool, layout: MatrixLayout) -> Result { - assert_eq!(layout.len(), layout.lda()); - let n = layout.len(); - let jobz = if calc_eigenvectors { - JobEv::All - } else { - JobEv::None - }; - let mut eigs = vec_uninit(n as usize); - let mut rwork = vec_uninit(3 * n as usize - 2 as usize); - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $gv( - &1, // ITYPE A*x = (lambda)*B*x - jobz.as_ptr(), - UPLO::Upper.as_ptr(), // dummy, working memory is not affected by UPLO - &n, - std::ptr::null_mut(), - &n, - std::ptr::null_mut(), - &n, - AsPtr::as_mut_ptr(&mut eigs), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - AsPtr::as_mut_ptr(&mut rwork), - &mut info, - ); - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(EighGeneralizedWork { - n, - eigs, - jobz, - work, - rwork: Some(rwork), - }) - } - - fn calc( - &mut self, - uplo: UPLO, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result<&[::Real]> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $gv( - &1, // ITYPE A*x = (lambda)*B*x - self.jobz.as_ptr(), - uplo.as_ptr(), - &self.n, - AsPtr::as_mut_ptr(a), - &self.n, - AsPtr::as_mut_ptr(b), - &self.n, - AsPtr::as_mut_ptr(&mut self.eigs), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - AsPtr::as_mut_ptr(self.rwork.as_mut().unwrap()), - &mut info, - ); - } - info.as_lapack_result()?; - Ok(unsafe { self.eigs.slice_assume_init_ref() }) - } - - fn eval( - mut self, - uplo: UPLO, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result::Real>> { - let _eig = self.calc(uplo, a, b)?; - Ok(unsafe { self.eigs.assume_init() }) - } - } - }; -} -impl_eigh_generalized_work_c!(c64, lapack_sys::zhegv_); -impl_eigh_generalized_work_c!(c32, lapack_sys::chegv_); - -macro_rules! impl_eigh_generalized_work_r { - ($f:ty, $gv:path) => { - impl EighGeneralizedWorkImpl for EighGeneralizedWork<$f> { - type Elem = $f; - - fn new(calc_eigenvectors: bool, layout: MatrixLayout) -> Result { - assert_eq!(layout.len(), layout.lda()); - let n = layout.len(); - let jobz = if calc_eigenvectors { - JobEv::All - } else { - JobEv::None - }; - let mut eigs = vec_uninit(n as usize); - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $gv( - &1, // ITYPE A*x = (lambda)*B*x - jobz.as_ptr(), - UPLO::Upper.as_ptr(), // dummy, working memory is not affected by UPLO - &n, - std::ptr::null_mut(), - &n, - std::ptr::null_mut(), - &n, - AsPtr::as_mut_ptr(&mut eigs), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ); - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(EighGeneralizedWork { - n, - eigs, - jobz, - work, - rwork: None, - }) - } - - fn calc( - &mut self, - uplo: UPLO, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result<&[::Real]> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $gv( - &1, // ITYPE A*x = (lambda)*B*x - self.jobz.as_ptr(), - uplo.as_ptr(), - &self.n, - AsPtr::as_mut_ptr(a), - &self.n, - AsPtr::as_mut_ptr(b), - &self.n, - AsPtr::as_mut_ptr(&mut self.eigs), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ); - } - info.as_lapack_result()?; - Ok(unsafe { self.eigs.slice_assume_init_ref() }) - } - - fn eval( - mut self, - uplo: UPLO, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result::Real>> { - let _eig = self.calc(uplo, a, b)?; - Ok(unsafe { self.eigs.assume_init() }) - } - } - }; -} -impl_eigh_generalized_work_r!(f64, lapack_sys::dsygv_); -impl_eigh_generalized_work_r!(f32, lapack_sys::ssygv_); diff --git a/lax/src/error.rs b/lax/src/error.rs deleted file mode 100644 index e1c314ee..00000000 --- a/lax/src/error.rs +++ /dev/null @@ -1,38 +0,0 @@ -use thiserror::Error; - -pub type Result = ::std::result::Result; - -#[derive(Error, Debug)] -pub enum Error { - #[error( - "Invalid value for LAPACK subroutine {}-th argument", - -return_code - )] - LapackInvalidValue { return_code: i32 }, - - #[error( - "Computational failure in LAPACK subroutine: return_code = {}", - return_code - )] - LapackComputationalFailure { return_code: i32 }, - - /// Strides of the array is not supported - #[error("Invalid shape")] - InvalidShape, -} - -pub trait AsLapackResult { - fn as_lapack_result(self) -> Result<()>; -} - -impl AsLapackResult for i32 { - fn as_lapack_result(self) -> Result<()> { - if self > 0 { - return Err(Error::LapackComputationalFailure { return_code: self }); - } - if self < 0 { - return Err(Error::LapackInvalidValue { return_code: self }); - } - Ok(()) - } -} diff --git a/lax/src/flags.rs b/lax/src/flags.rs deleted file mode 100644 index f9dea20d..00000000 --- a/lax/src/flags.rs +++ /dev/null @@ -1,140 +0,0 @@ -//! Charactor flags, e.g. `'T'`, used in LAPACK API -use core::ffi::c_char; - -/// Upper/Lower specification for seveal usages -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(u8)] -pub enum UPLO { - Upper = b'U', - Lower = b'L', -} - -impl UPLO { - pub fn t(self) -> Self { - match self { - UPLO::Upper => UPLO::Lower, - UPLO::Lower => UPLO::Upper, - } - } - - /// To use Fortran LAPACK API in lapack-sys crate - pub fn as_ptr(&self) -> *const c_char { - self as *const UPLO as *const c_char - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(u8)] -pub enum Transpose { - No = b'N', - Transpose = b'T', - Hermite = b'C', -} - -impl Transpose { - /// To use Fortran LAPACK API in lapack-sys crate - pub fn as_ptr(&self) -> *const c_char { - self as *const Transpose as *const c_char - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(u8)] -pub enum NormType { - One = b'O', - Infinity = b'I', - Frobenius = b'F', -} - -impl NormType { - pub fn transpose(self) -> Self { - match self { - NormType::One => NormType::Infinity, - NormType::Infinity => NormType::One, - NormType::Frobenius => NormType::Frobenius, - } - } - - /// To use Fortran LAPACK API in lapack-sys crate - pub fn as_ptr(&self) -> *const c_char { - self as *const NormType as *const c_char - } -} - -/// Flag for calculating eigenvectors or not -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(u8)] -pub enum JobEv { - /// Calculate eigenvectors in addition to eigenvalues - All = b'V', - /// Do not calculate eigenvectors. Only calculate eigenvalues. - None = b'N', -} - -impl JobEv { - pub fn is_calc(&self) -> bool { - match self { - JobEv::All => true, - JobEv::None => false, - } - } - - pub fn then T>(&self, f: F) -> Option { - if self.is_calc() { - Some(f()) - } else { - None - } - } - - /// To use Fortran LAPACK API in lapack-sys crate - pub fn as_ptr(&self) -> *const c_char { - self as *const JobEv as *const c_char - } -} - -/// Specifies how many singular vectors are computed -/// -/// For an input matrix $A$ of shape $m \times n$, -/// the following are computed on the singular value decomposition $A = U\Sigma V^T$: -#[cfg_attr(doc, katexit::katexit)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(u8)] -pub enum JobSvd { - /// All $m$ columns of $U$, and/or all $n$ rows of $V^T$. - All = b'A', - /// The first $\min(m, n)$ columns of $U$ and/or the first $\min(m, n)$ rows of $V^T$. - Some = b'S', - /// No columns of $U$ and/or rows of $V^T$. - None = b'N', -} - -impl JobSvd { - pub fn from_bool(calc_uv: bool) -> Self { - if calc_uv { - JobSvd::All - } else { - JobSvd::None - } - } - - pub fn as_ptr(&self) -> *const c_char { - self as *const JobSvd as *const c_char - } -} - -/// Specify whether input triangular matrix is unit or not -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(u8)] -pub enum Diag { - /// Unit triangular matrix, i.e. all diagonal elements of the matrix are `1` - Unit = b'U', - /// Non-unit triangular matrix. Its diagonal elements may be different from `1` - NonUnit = b'N', -} - -impl Diag { - pub fn as_ptr(&self) -> *const c_char { - self as *const Diag as *const c_char - } -} diff --git a/lax/src/layout.rs b/lax/src/layout.rs deleted file mode 100644 index 28b35122..00000000 --- a/lax/src/layout.rs +++ /dev/null @@ -1,280 +0,0 @@ -//! Memory layout of matrices -//! -//! Different from ndarray format which consists of shape and strides, -//! matrix format in LAPACK consists of row or column size and leading dimension. -//! -//! ndarray format and stride -//! -------------------------- -//! -//! Let us consider 3-dimensional array for explaining ndarray structure. -//! The address of `(x,y,z)`-element in ndarray satisfies following relation: -//! -//! ```text -//! shape = [Nx, Ny, Nz] -//! where Nx > 0, Ny > 0, Nz > 0 -//! stride = [Sx, Sy, Sz] -//! -//! &data[(x, y, z)] = &data[(0, 0, 0)] + Sx*x + Sy*y + Sz*z -//! for x < Nx, y < Ny, z < Nz -//! ``` -//! -//! The array is called -//! -//! - C-continuous if `[Sx, Sy, Sz] = [Nz*Ny, Nz, 1]` -//! - F(Fortran)-continuous if `[Sx, Sy, Sz] = [1, Nx, Nx*Ny]` -//! -//! Strides of ndarray `[Sx, Sy, Sz]` take arbitrary value, -//! e.g. it can be non-ordered `Sy > Sx > Sz`, or can be negative `Sx < 0`. -//! If the minimum of `[Sx, Sy, Sz]` equals to `1`, -//! the value of elements fills `data` memory region and called "continuous". -//! Non-continuous ndarray is useful to get sub-array without copying data. -//! -//! Matrix layout for LAPACK -//! ------------------------- -//! -//! LAPACK interface focuses on the linear algebra operations for F-continuous 2-dimensional array. -//! Under this restriction, stride becomes far simpler; we only have to consider the case `[1, S]` -//! This `S` for a matrix `A` is called "leading dimension of the array A" in LAPACK document, and denoted by `lda`. -//! - -use super::*; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum MatrixLayout { - C { row: i32, lda: i32 }, - F { col: i32, lda: i32 }, -} - -impl MatrixLayout { - pub fn size(&self) -> (i32, i32) { - match *self { - MatrixLayout::C { row, lda } => (row, lda), - MatrixLayout::F { col, lda } => (lda, col), - } - } - - pub fn resized(&self, row: i32, col: i32) -> MatrixLayout { - match *self { - MatrixLayout::C { .. } => MatrixLayout::C { row, lda: col }, - MatrixLayout::F { .. } => MatrixLayout::F { col, lda: row }, - } - } - - pub fn lda(&self) -> i32 { - std::cmp::max( - 1, - match *self { - MatrixLayout::C { lda, .. } | MatrixLayout::F { lda, .. } => lda, - }, - ) - } - - pub fn len(&self) -> i32 { - match *self { - MatrixLayout::C { row, .. } => row, - MatrixLayout::F { col, .. } => col, - } - } - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - pub fn same_order(&self, other: &MatrixLayout) -> bool { - match (self, other) { - (MatrixLayout::C { .. }, MatrixLayout::C { .. }) => true, - (MatrixLayout::F { .. }, MatrixLayout::F { .. }) => true, - _ => false, - } - } - - pub fn toggle_order(&self) -> Self { - match *self { - MatrixLayout::C { row, lda } => MatrixLayout::F { lda: row, col: lda }, - MatrixLayout::F { col, lda } => MatrixLayout::C { row: lda, lda: col }, - } - } - - /// Transpose without changing memory representation - /// - /// C-contigious row=2, lda=3 - /// - /// ```text - /// [[1, 2, 3] - /// [4, 5, 6]] - /// ``` - /// - /// and F-contigious col=2, lda=3 - /// - /// ```text - /// [[1, 4] - /// [2, 5] - /// [3, 6]] - /// ``` - /// - /// have same memory representation `[1, 2, 3, 4, 5, 6]`, and this toggles them. - /// - /// ``` - /// # use lax::layout::*; - /// let layout = MatrixLayout::C { row: 2, lda: 3 }; - /// assert_eq!(layout.t(), MatrixLayout::F { col: 2, lda: 3 }); - /// ``` - pub fn t(&self) -> Self { - match *self { - MatrixLayout::C { row, lda } => MatrixLayout::F { col: row, lda }, - MatrixLayout::F { col, lda } => MatrixLayout::C { row: col, lda }, - } - } -} - -/// In-place transpose of a square matrix by keeping F/C layout -/// -/// Transpose for C-continuous array -/// -/// ```rust -/// # use lax::layout::*; -/// let layout = MatrixLayout::C { row: 2, lda: 2 }; -/// let mut a = vec![1., 2., 3., 4.]; -/// square_transpose(layout, &mut a); -/// assert_eq!(a, &[1., 3., 2., 4.]); -/// ``` -/// -/// Transpose for F-continuous array -/// -/// ```rust -/// # use lax::layout::*; -/// let layout = MatrixLayout::F { col: 2, lda: 2 }; -/// let mut a = vec![1., 3., 2., 4.]; -/// square_transpose(layout, &mut a); -/// assert_eq!(a, &[1., 2., 3., 4.]); -/// ``` -/// -/// Panics -/// ------ -/// - If size of `a` and `layout` size mismatch -/// -pub fn square_transpose(layout: MatrixLayout, a: &mut [T]) { - let (m, n) = layout.size(); - let n = n as usize; - let m = m as usize; - assert_eq!(a.len(), n * m); - for i in 0..m { - for j in (i + 1)..n { - let a_ij = a[i * n + j]; - let a_ji = a[j * m + i]; - a[i * n + j] = a_ji; - a[j * m + i] = a_ij; - } - } -} - -/// Out-place transpose for general matrix -/// -/// Examples -/// --------- -/// -/// ```rust -/// # use lax::layout::*; -/// let layout = MatrixLayout::C { row: 2, lda: 3 }; -/// let a = vec![1., 2., 3., 4., 5., 6.]; -/// let (l, b) = transpose(layout, &a); -/// assert_eq!(l, MatrixLayout::F { col: 3, lda: 2 }); -/// assert_eq!(b, &[1., 4., 2., 5., 3., 6.]); -/// ``` -/// -/// ```rust -/// # use lax::layout::*; -/// let layout = MatrixLayout::F { col: 2, lda: 3 }; -/// let a = vec![1., 2., 3., 4., 5., 6.]; -/// let (l, b) = transpose(layout, &a); -/// assert_eq!(l, MatrixLayout::C { row: 3, lda: 2 }); -/// assert_eq!(b, &[1., 4., 2., 5., 3., 6.]); -/// ``` -/// -/// Panics -/// ------ -/// - If input array size and `layout` size mismatch -/// -pub fn transpose(layout: MatrixLayout, input: &[T]) -> (MatrixLayout, Vec) { - let (m, n) = layout.size(); - let transposed = layout.resized(n, m).t(); - let m = m as usize; - let n = n as usize; - assert_eq!(input.len(), m * n); - - let mut out: Vec> = vec_uninit(m * n); - - match layout { - MatrixLayout::C { .. } => { - for i in 0..m { - for j in 0..n { - out[j * m + i].write(input[i * n + j]); - } - } - } - MatrixLayout::F { .. } => { - for i in 0..m { - for j in 0..n { - out[i * n + j].write(input[j * m + i]); - } - } - } - } - (transposed, unsafe { out.assume_init() }) -} - -/// Out-place transpose for general matrix -/// -/// Examples -/// --------- -/// -/// ```rust -/// # use lax::layout::*; -/// let layout = MatrixLayout::C { row: 2, lda: 3 }; -/// let a = vec![1., 2., 3., 4., 5., 6.]; -/// let mut b = vec![0.0; a.len()]; -/// let l = transpose_over(layout, &a, &mut b); -/// assert_eq!(l, MatrixLayout::F { col: 3, lda: 2 }); -/// assert_eq!(b, &[1., 4., 2., 5., 3., 6.]); -/// ``` -/// -/// ```rust -/// # use lax::layout::*; -/// let layout = MatrixLayout::F { col: 2, lda: 3 }; -/// let a = vec![1., 2., 3., 4., 5., 6.]; -/// let mut b = vec![0.0; a.len()]; -/// let l = transpose_over(layout, &a, &mut b); -/// assert_eq!(l, MatrixLayout::C { row: 3, lda: 2 }); -/// assert_eq!(b, &[1., 4., 2., 5., 3., 6.]); -/// ``` -/// -/// Panics -/// ------ -/// - If input array sizes and `layout` size mismatch -/// -pub fn transpose_over(layout: MatrixLayout, from: &[T], to: &mut [T]) -> MatrixLayout { - let (m, n) = layout.size(); - let transposed = layout.resized(n, m).t(); - let m = m as usize; - let n = n as usize; - assert_eq!(from.len(), m * n); - assert_eq!(to.len(), m * n); - - match layout { - MatrixLayout::C { .. } => { - for i in 0..m { - for j in 0..n { - to[j * m + i] = from[i * n + j]; - } - } - } - MatrixLayout::F { .. } => { - for i in 0..m { - for j in 0..n { - to[i * n + j] = from[j * m + i]; - } - } - } - } - transposed -} diff --git a/lax/src/least_squares.rs b/lax/src/least_squares.rs deleted file mode 100644 index d0bb7def..00000000 --- a/lax/src/least_squares.rs +++ /dev/null @@ -1,338 +0,0 @@ -//! Least squares - -use crate::{error::*, layout::*, *}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -/// Result of LeastSquares -pub struct LeastSquaresOwned { - /// singular values - pub singular_values: Vec, - /// The rank of the input matrix A - pub rank: i32, -} - -/// Result of LeastSquares -pub struct LeastSquaresRef<'work, A: Scalar> { - /// singular values - pub singular_values: &'work [A::Real], - /// The rank of the input matrix A - pub rank: i32, -} - -pub struct LeastSquaresWork { - pub a_layout: MatrixLayout, - pub b_layout: MatrixLayout, - pub singular_values: Vec>, - pub work: Vec>, - pub iwork: Vec>, - pub rwork: Option>>, -} - -pub trait LeastSquaresWorkImpl: Sized { - type Elem: Scalar; - fn new(a_layout: MatrixLayout, b_layout: MatrixLayout) -> Result; - fn calc( - &mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result>; - fn eval( - self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result>; -} - -macro_rules! impl_least_squares_work_c { - ($c:ty, $lsd:path) => { - impl LeastSquaresWorkImpl for LeastSquaresWork<$c> { - type Elem = $c; - - fn new(a_layout: MatrixLayout, b_layout: MatrixLayout) -> Result { - let (m, n) = a_layout.size(); - let (m_, nrhs) = b_layout.size(); - let k = m.min(n); - assert!(m_ >= m); - - let rcond = -1.; - let mut singular_values = vec_uninit(k as usize); - let mut rank: i32 = 0; - - // eval work size - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - let mut iwork_size = [0]; - let mut rwork = [::Real::zero()]; - unsafe { - $lsd( - &m, - &n, - &nrhs, - std::ptr::null_mut(), - &m, - std::ptr::null_mut(), - &m_, - AsPtr::as_mut_ptr(&mut singular_values), - &rcond, - &mut rank, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - AsPtr::as_mut_ptr(&mut rwork), - iwork_size.as_mut_ptr(), - &mut info, - ) - }; - info.as_lapack_result()?; - - let lwork = work_size[0].to_usize().unwrap(); - let liwork = iwork_size[0].to_usize().unwrap(); - let lrwork = rwork[0].to_usize().unwrap(); - - let work = vec_uninit(lwork); - let iwork = vec_uninit(liwork); - let rwork = vec_uninit(lrwork); - - Ok(LeastSquaresWork { - a_layout, - b_layout, - work, - iwork, - rwork: Some(rwork), - singular_values, - }) - } - - fn calc( - &mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result> { - let (m, n) = self.a_layout.size(); - let (m_, nrhs) = self.b_layout.size(); - assert!(m_ >= m); - - let lwork = self.work.len().to_i32().unwrap(); - - // Transpose if a is C-continuous - let mut a_t = None; - let _ = match self.a_layout { - MatrixLayout::C { .. } => { - let (layout, t) = transpose(self.a_layout, a); - a_t = Some(t); - layout - } - MatrixLayout::F { .. } => self.a_layout, - }; - - // Transpose if b is C-continuous - let mut b_t = None; - let b_layout = match self.b_layout { - MatrixLayout::C { .. } => { - let (layout, t) = transpose(self.b_layout, b); - b_t = Some(t); - layout - } - MatrixLayout::F { .. } => self.b_layout, - }; - - let rcond: ::Real = -1.; - let mut rank: i32 = 0; - - let mut info = 0; - unsafe { - $lsd( - &m, - &n, - &nrhs, - AsPtr::as_mut_ptr(a_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(a)), - &m, - AsPtr::as_mut_ptr(b_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(b)), - &m_, - AsPtr::as_mut_ptr(&mut self.singular_values), - &rcond, - &mut rank, - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - AsPtr::as_mut_ptr(self.rwork.as_mut().unwrap()), - AsPtr::as_mut_ptr(&mut self.iwork), - &mut info, - ); - } - info.as_lapack_result()?; - - let singular_values = unsafe { self.singular_values.slice_assume_init_ref() }; - - // Skip a_t -> a transpose because A has been destroyed - // Re-transpose b - if let Some(b_t) = b_t { - transpose_over(b_layout, &b_t, b); - } - - Ok(LeastSquaresRef { - singular_values, - rank, - }) - } - - fn eval( - mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result> { - let LeastSquaresRef { rank, .. } = self.calc(a, b)?; - let singular_values = unsafe { self.singular_values.assume_init() }; - Ok(LeastSquaresOwned { - singular_values, - rank, - }) - } - } - }; -} -impl_least_squares_work_c!(c64, lapack_sys::zgelsd_); -impl_least_squares_work_c!(c32, lapack_sys::cgelsd_); - -macro_rules! impl_least_squares_work_r { - ($c:ty, $lsd:path) => { - impl LeastSquaresWorkImpl for LeastSquaresWork<$c> { - type Elem = $c; - - fn new(a_layout: MatrixLayout, b_layout: MatrixLayout) -> Result { - let (m, n) = a_layout.size(); - let (m_, nrhs) = b_layout.size(); - let k = m.min(n); - assert!(m_ >= m); - - let rcond = -1.; - let mut singular_values = vec_uninit(k as usize); - let mut rank: i32 = 0; - - // eval work size - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - let mut iwork_size = [0]; - unsafe { - $lsd( - &m, - &n, - &nrhs, - std::ptr::null_mut(), - &m, - std::ptr::null_mut(), - &m_, - AsPtr::as_mut_ptr(&mut singular_values), - &rcond, - &mut rank, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - iwork_size.as_mut_ptr(), - &mut info, - ) - }; - info.as_lapack_result()?; - - let lwork = work_size[0].to_usize().unwrap(); - let liwork = iwork_size[0].to_usize().unwrap(); - - let work = vec_uninit(lwork); - let iwork = vec_uninit(liwork); - - Ok(LeastSquaresWork { - a_layout, - b_layout, - work, - iwork, - rwork: None, - singular_values, - }) - } - - fn calc( - &mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result> { - let (m, n) = self.a_layout.size(); - let (m_, nrhs) = self.b_layout.size(); - assert!(m_ >= m); - - let lwork = self.work.len().to_i32().unwrap(); - - // Transpose if a is C-continuous - let mut a_t = None; - let _ = match self.a_layout { - MatrixLayout::C { .. } => { - let (layout, t) = transpose(self.a_layout, a); - a_t = Some(t); - layout - } - MatrixLayout::F { .. } => self.a_layout, - }; - - // Transpose if b is C-continuous - let mut b_t = None; - let b_layout = match self.b_layout { - MatrixLayout::C { .. } => { - let (layout, t) = transpose(self.b_layout, b); - b_t = Some(t); - layout - } - MatrixLayout::F { .. } => self.b_layout, - }; - - let rcond: ::Real = -1.; - let mut rank: i32 = 0; - - let mut info = 0; - unsafe { - $lsd( - &m, - &n, - &nrhs, - AsPtr::as_mut_ptr(a_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(a)), - &m, - AsPtr::as_mut_ptr(b_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(b)), - &m_, - AsPtr::as_mut_ptr(&mut self.singular_values), - &rcond, - &mut rank, - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - AsPtr::as_mut_ptr(&mut self.iwork), - &mut info, - ); - } - info.as_lapack_result()?; - - let singular_values = unsafe { self.singular_values.slice_assume_init_ref() }; - - // Skip a_t -> a transpose because A has been destroyed - // Re-transpose b - if let Some(b_t) = b_t { - transpose_over(b_layout, &b_t, b); - } - - Ok(LeastSquaresRef { - singular_values, - rank, - }) - } - - fn eval( - mut self, - a: &mut [Self::Elem], - b: &mut [Self::Elem], - ) -> Result> { - let LeastSquaresRef { rank, .. } = self.calc(a, b)?; - let singular_values = unsafe { self.singular_values.assume_init() }; - Ok(LeastSquaresOwned { - singular_values, - rank, - }) - } - } - }; -} -impl_least_squares_work_r!(f64, lapack_sys::dgelsd_); -impl_least_squares_work_r!(f32, lapack_sys::sgelsd_); diff --git a/lax/src/lib.rs b/lax/src/lib.rs deleted file mode 100644 index b3d8cca1..00000000 --- a/lax/src/lib.rs +++ /dev/null @@ -1,576 +0,0 @@ -//! Safe Rust wrapper for LAPACK without external dependency. -//! -//! [Lapack] trait -//! ---------------- -//! -//! This crates provides LAPACK wrapper as a traits. -//! For example, LU decomposition of general matrices is provided like: -//! -//! ```ignore -//! pub trait Lapack { -//! fn lu(l: MatrixLayout, a: &mut [Self]) -> Result; -//! } -//! ``` -//! -//! see [Lapack] for detail. -//! This trait is implemented for [f32], [f64], [c32] which is an alias to `num::Complex`, -//! and [c64] which is an alias to `num::Complex`. -//! You can use it like `f64::lu`: -//! -//! ``` -//! use lax::{Lapack, layout::MatrixLayout, Transpose}; -//! -//! let mut a = vec![ -//! 1.0, 2.0, -//! 3.0, 4.0 -//! ]; -//! let mut b = vec![1.0, 2.0]; -//! let layout = MatrixLayout::C { row: 2, lda: 2 }; -//! let pivot = f64::lu(layout, &mut a).unwrap(); -//! f64::solve(layout, Transpose::No, &a, &pivot, &mut b).unwrap(); -//! ``` -//! -//! When you want to write generic algorithm for real and complex matrices, -//! this trait can be used as a trait bound: -//! -//! ``` -//! use lax::{Lapack, layout::MatrixLayout, Transpose}; -//! -//! fn solve_at_once(layout: MatrixLayout, a: &mut [T], b: &mut [T]) -> Result<(), lax::error::Error> { -//! let pivot = T::lu(layout, a)?; -//! T::solve(layout, Transpose::No, a, &pivot, b)?; -//! Ok(()) -//! } -//! ``` -//! -//! There are several similar traits as described below to keep development easy. -//! They are merged into a single trait, [Lapack]. -//! -//! Linear equation, Inverse matrix, Condition number -//! -------------------------------------------------- -//! -//! According to the property input metrix, several types of triangular decomposition are used: -//! -//! - [solve] module provides methods for LU-decomposition for general matrix. -//! - [solveh] module provides methods for Bunch-Kaufman diagonal pivoting method for symmetric/Hermitian indefinite matrix. -//! - [cholesky] module provides methods for Cholesky decomposition for symmetric/Hermitian positive dinite matrix. -//! -//! Eigenvalue Problem -//! ------------------- -//! -//! According to the property input metrix, -//! there are several types of eigenvalue problem API -//! -//! - [eig] module for eigenvalue problem for general matrix. -//! - [eig_generalized] module for generalized eigenvalue problem for general matrix. -//! - [eigh] module for eigenvalue problem for symmetric/Hermitian matrix. -//! - [eigh_generalized] module for generalized eigenvalue problem for symmetric/Hermitian matrix. -//! -//! Singular Value Decomposition -//! ----------------------------- -//! -//! - [svd] module for singular value decomposition (SVD) for general matrix -//! - [svddc] module for singular value decomposition (SVD) with divided-and-conquer algorithm for general matrix -//! - [least_squares] module for solving least square problem using SVD -//! - -#![deny(rustdoc::broken_intra_doc_links, rustdoc::private_intra_doc_links)] - -#[cfg(any( - feature = "intel-mkl-static", //decprecated - feature = "intel-mkl-dynamic", //decprecated - feature = "intel-mkl-dynamic-lp64-iomp", - feature = "intel-mkl-dynamic-lp64-seq", - feature = "intel-mkl-static-ilp64-iomp", - feature = "intel-mkl-static-lp64-iomp", - feature = "intel-mkl-dynamic-ilp64-iomp", - feature = "intel-mkl-static-ilp64-seq", - feature = "intel-mkl-static-lp64-seq" -))] -extern crate intel_mkl_src as _src; - -#[cfg(any(feature = "openblas-system", feature = "openblas-static"))] -extern crate openblas_src as _src; - -#[cfg(any(feature = "netlib-system", feature = "netlib-static"))] -extern crate netlib_src as _src; - -pub mod alloc; -pub mod cholesky; -pub mod eig; -pub mod eig_generalized; -pub mod eigh; -pub mod eigh_generalized; -pub mod error; -pub mod flags; -pub mod layout; -pub mod least_squares; -pub mod opnorm; -pub mod qr; -pub mod rcond; -pub mod solve; -pub mod solveh; -pub mod svd; -pub mod svddc; -pub mod triangular; -pub mod tridiagonal; - -pub use crate::eig_generalized::GeneralizedEigenvalue; - -pub use self::flags::*; -pub use self::least_squares::LeastSquaresOwned; -pub use self::svd::{SvdOwned, SvdRef}; -pub use self::tridiagonal::{LUFactorizedTridiagonal, Tridiagonal}; - -use self::{alloc::*, error::*, layout::*}; -use cauchy::*; -use std::mem::MaybeUninit; - -pub type Pivot = Vec; - -#[cfg_attr(doc, katexit::katexit)] -/// Trait for primitive types which implements LAPACK subroutines -pub trait Lapack: Scalar { - /// Compute right eigenvalue and eigenvectors for a general matrix - fn eig( - calc_v: bool, - l: MatrixLayout, - a: &mut [Self], - ) -> Result<(Vec, Vec)>; - - /// Compute right eigenvalue and eigenvectors for a general matrix - fn eig_generalized( - calc_v: bool, - l: MatrixLayout, - a: &mut [Self], - b: &mut [Self], - thresh_opt: Option, - ) -> Result<( - Vec>, - Vec, - )>; - - /// Compute right eigenvalue and eigenvectors for a symmetric or Hermitian matrix - fn eigh( - calc_eigenvec: bool, - layout: MatrixLayout, - uplo: UPLO, - a: &mut [Self], - ) -> Result>; - - /// Compute right eigenvalue and eigenvectors for a symmetric or Hermitian matrix - fn eigh_generalized( - calc_eigenvec: bool, - layout: MatrixLayout, - uplo: UPLO, - a: &mut [Self], - b: &mut [Self], - ) -> Result>; - - /// Execute Householder reflection as the first step of QR-decomposition - /// - /// For C-continuous array, - /// this will call LQ-decomposition of the transposed matrix $ A^T = LQ^T $ - fn householder(l: MatrixLayout, a: &mut [Self]) -> Result>; - - /// Reconstruct Q-matrix from Householder-reflectors - fn q(l: MatrixLayout, a: &mut [Self], tau: &[Self]) -> Result<()>; - - /// Execute QR-decomposition at once - fn qr(l: MatrixLayout, a: &mut [Self]) -> Result>; - - /// Compute singular-value decomposition (SVD) - fn svd(l: MatrixLayout, calc_u: bool, calc_vt: bool, a: &mut [Self]) -> Result>; - - /// Compute singular value decomposition (SVD) with divide-and-conquer algorithm - fn svddc(layout: MatrixLayout, jobz: JobSvd, a: &mut [Self]) -> Result>; - - /// Compute a vector $x$ which minimizes Euclidian norm $\| Ax - b\|$ - /// for a given matrix $A$ and a vector $b$. - fn least_squares( - a_layout: MatrixLayout, - a: &mut [Self], - b: &mut [Self], - ) -> Result>; - - /// Solve least square problems $\argmin_X \| AX - B\|$ - fn least_squares_nrhs( - a_layout: MatrixLayout, - a: &mut [Self], - b_layout: MatrixLayout, - b: &mut [Self], - ) -> Result>; - - /// Computes the LU decomposition of a general $m \times n$ matrix - /// with partial pivoting with row interchanges. - /// - /// For a given matrix $A$, LU decomposition is described as $A = PLU$ where: - /// - /// - $L$ is lower matrix - /// - $U$ is upper matrix - /// - $P$ is permutation matrix represented by [Pivot] - /// - /// This is designed as two step computation according to LAPACK API: - /// - /// 1. Factorize input matrix $A$ into $L$, $U$, and $P$. - /// 2. Solve linear equation $Ax = b$ by [Lapack::solve] - /// or compute inverse matrix $A^{-1}$ by [Lapack::inv] using the output of LU decomposition. - /// - /// Output - /// ------- - /// - $U$ and $L$ are stored in `a` after LU decomposition has succeeded. - /// - $P$ is returned as [Pivot] - /// - /// Error - /// ------ - /// - if the matrix is singular - /// - On this case, `return_code` in [Error::LapackComputationalFailure] means - /// `return_code`-th diagonal element of $U$ becomes zero. - /// - fn lu(l: MatrixLayout, a: &mut [Self]) -> Result; - - /// Compute inverse matrix $A^{-1}$ from the output of LU-decomposition - fn inv(l: MatrixLayout, a: &mut [Self], p: &Pivot) -> Result<()>; - - /// Solve linear equations $Ax = b$ using the output of LU-decomposition - fn solve(l: MatrixLayout, t: Transpose, a: &[Self], p: &Pivot, b: &mut [Self]) -> Result<()>; - - /// Factorize symmetric/Hermitian matrix using Bunch-Kaufman diagonal pivoting method - /// - /// For a given symmetric matrix $A$, - /// this method factorizes $A = U^T D U$ or $A = L D L^T$ where - /// - /// - $U$ (or $L$) are 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. - /// - /// This takes two-step approach based in LAPACK: - /// - /// 1. Factorize given matrix $A$ into upper ($U$) or lower ($L$) form with diagonal matrix $D$ - /// 2. Then solve linear equation $Ax = b$, and/or calculate inverse matrix $A^{-1}$ - /// - fn bk(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result; - - /// Compute inverse matrix $A^{-1}$ using the result of [Lapack::bk] - fn invh(l: MatrixLayout, uplo: UPLO, a: &mut [Self], ipiv: &Pivot) -> Result<()>; - - /// Solve symmetric/Hermitian linear equation $Ax = b$ using the result of [Lapack::bk] - fn solveh(l: MatrixLayout, uplo: UPLO, a: &[Self], ipiv: &Pivot, b: &mut [Self]) -> Result<()>; - - /// Solve symmetric/Hermitian positive-definite linear equations using Cholesky decomposition - /// - /// For a given positive definite matrix $A$, - /// Cholesky decomposition is described as $A = U^T U$ or $A = LL^T$ where - /// - /// - $L$ is lower matrix - /// - $U$ is upper matrix - /// - /// This is designed as two step computation according to LAPACK API - /// - /// 1. Factorize input matrix $A$ into $L$ or $U$ - /// 2. Solve linear equation $Ax = b$ by [Lapack::solve_cholesky] - /// or compute inverse matrix $A^{-1}$ by [Lapack::inv_cholesky] - /// - fn cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()>; - - /// Compute inverse matrix $A^{-1}$ using $U$ or $L$ calculated by [Lapack::cholesky] - fn inv_cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()>; - - /// Solve linear equation $Ax = b$ using $U$ or $L$ calculated by [Lapack::cholesky] - fn solve_cholesky(l: MatrixLayout, uplo: UPLO, a: &[Self], b: &mut [Self]) -> Result<()>; - - /// Estimates the the reciprocal of the condition number of the matrix in 1-norm. - /// - /// `anorm` should be the 1-norm of the matrix `a`. - fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result; - - /// Compute norm of matrices - /// - /// For a $n \times m$ matrix - /// $$ - /// A = \begin{pmatrix} - /// a_{11} & \cdots & a_{1m} \\\\ - /// \vdots & \ddots & \vdots \\\\ - /// a_{n1} & \cdots & a_{nm} - /// \end{pmatrix} - /// $$ - /// LAPACK can compute three types of norms: - /// - /// - Operator norm based on 1-norm for its domain linear space: - /// $$ - /// \Vert A \Vert_1 = \sup_{\Vert x \Vert_1 = 1} \Vert Ax \Vert_1 - /// = \max_{1 \le j \le m } \sum_{i=1}^n |a_{ij}| - /// $$ - /// where - /// $\Vert x\Vert_1 = \sum_{j=1}^m |x_j|$ - /// is 1-norm for a vector $x$. - /// - /// - Operator norm based on $\infty$-norm for its domain linear space: - /// $$ - /// \Vert A \Vert_\infty = \sup_{\Vert x \Vert_\infty = 1} \Vert Ax \Vert_\infty - /// = \max_{1 \le i \le n } \sum_{j=1}^m |a_{ij}| - /// $$ - /// where - /// $\Vert x\Vert_\infty = \max_{j=1}^m |x_j|$ - /// is $\infty$-norm for a vector $x$. - /// - /// - Frobenious norm - /// $$ - /// \Vert A \Vert_F = \sqrt{\mathrm{Tr} \left(AA^\dagger\right)} = \sqrt{\sum_{i=1}^n \sum_{j=1}^m |a_{ij}|^2} - /// $$ - /// - fn opnorm(t: NormType, l: MatrixLayout, a: &[Self]) -> Self::Real; - - fn solve_triangular( - al: MatrixLayout, - bl: MatrixLayout, - uplo: UPLO, - d: Diag, - a: &[Self], - b: &mut [Self], - ) -> Result<()>; - - /// Computes the LU factorization of a tridiagonal `m x n` matrix `a` using - /// partial pivoting with row interchanges. - fn lu_tridiagonal(a: Tridiagonal) -> Result>; - - fn rcond_tridiagonal(lu: &LUFactorizedTridiagonal) -> Result; - - fn solve_tridiagonal( - lu: &LUFactorizedTridiagonal, - bl: MatrixLayout, - t: Transpose, - b: &mut [Self], - ) -> Result<()>; -} - -macro_rules! impl_lapack { - ($s:ty) => { - impl Lapack for $s { - fn eig( - calc_v: bool, - l: MatrixLayout, - a: &mut [Self], - ) -> Result<(Vec, Vec)> { - use eig::*; - let work = EigWork::<$s>::new(calc_v, l)?; - let EigOwned { eigs, vr, vl } = work.eval(a)?; - Ok((eigs, vr.or(vl).unwrap_or_default())) - } - - fn eig_generalized( - calc_v: bool, - l: MatrixLayout, - a: &mut [Self], - b: &mut [Self], - thresh_opt: Option, - ) -> Result<( - Vec>, - Vec, - )> { - use eig_generalized::*; - let work = EigGeneralizedWork::<$s>::new(calc_v, l)?; - let eig_generalized_owned = work.eval(a, b)?; - let eigs = eig_generalized_owned.calc_eigs(thresh_opt); - let vr = eig_generalized_owned.vr; - let vl = eig_generalized_owned.vl; - Ok((eigs, vr.or(vl).unwrap_or_default())) - } - - fn eigh( - calc_eigenvec: bool, - layout: MatrixLayout, - uplo: UPLO, - a: &mut [Self], - ) -> Result> { - use eigh::*; - let work = EighWork::<$s>::new(calc_eigenvec, layout)?; - work.eval(uplo, a) - } - - fn eigh_generalized( - calc_eigenvec: bool, - layout: MatrixLayout, - uplo: UPLO, - a: &mut [Self], - b: &mut [Self], - ) -> Result> { - use eigh_generalized::*; - let work = EighGeneralizedWork::<$s>::new(calc_eigenvec, layout)?; - work.eval(uplo, a, b) - } - - fn householder(l: MatrixLayout, a: &mut [Self]) -> Result> { - use qr::*; - let work = HouseholderWork::<$s>::new(l)?; - work.eval(a) - } - - fn q(l: MatrixLayout, a: &mut [Self], tau: &[Self]) -> Result<()> { - use qr::*; - let mut work = QWork::<$s>::new(l)?; - work.calc(a, tau)?; - Ok(()) - } - - fn qr(l: MatrixLayout, a: &mut [Self]) -> Result> { - let tau = Self::householder(l, a)?; - let r = Vec::from(&*a); - Self::q(l, a, &tau)?; - Ok(r) - } - - fn svd( - l: MatrixLayout, - calc_u: bool, - calc_vt: bool, - a: &mut [Self], - ) -> Result> { - use svd::*; - let work = SvdWork::<$s>::new(l, calc_u, calc_vt)?; - work.eval(a) - } - - fn svddc(layout: MatrixLayout, jobz: JobSvd, a: &mut [Self]) -> Result> { - use svddc::*; - let work = SvdDcWork::<$s>::new(layout, jobz)?; - work.eval(a) - } - - fn least_squares( - l: MatrixLayout, - a: &mut [Self], - b: &mut [Self], - ) -> Result> { - let b_layout = l.resized(b.len() as i32, 1); - Self::least_squares_nrhs(l, a, b_layout, b) - } - - fn least_squares_nrhs( - a_layout: MatrixLayout, - a: &mut [Self], - b_layout: MatrixLayout, - b: &mut [Self], - ) -> Result> { - use least_squares::*; - let work = LeastSquaresWork::<$s>::new(a_layout, b_layout)?; - work.eval(a, b) - } - - fn lu(l: MatrixLayout, a: &mut [Self]) -> Result { - use solve::*; - LuImpl::lu(l, a) - } - - fn inv(l: MatrixLayout, a: &mut [Self], p: &Pivot) -> Result<()> { - use solve::*; - let mut work = InvWork::<$s>::new(l)?; - work.calc(a, p)?; - Ok(()) - } - - fn solve( - l: MatrixLayout, - t: Transpose, - a: &[Self], - p: &Pivot, - b: &mut [Self], - ) -> Result<()> { - use solve::*; - SolveImpl::solve(l, t, a, p, b) - } - - fn bk(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result { - use solveh::*; - let work = BkWork::<$s>::new(l)?; - work.eval(uplo, a) - } - - fn invh(l: MatrixLayout, uplo: UPLO, a: &mut [Self], ipiv: &Pivot) -> Result<()> { - use solveh::*; - let mut work = InvhWork::<$s>::new(l)?; - work.calc(uplo, a, ipiv) - } - - fn solveh( - l: MatrixLayout, - uplo: UPLO, - a: &[Self], - ipiv: &Pivot, - b: &mut [Self], - ) -> Result<()> { - use solveh::*; - SolvehImpl::solveh(l, uplo, a, ipiv, b) - } - - fn cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()> { - use cholesky::*; - CholeskyImpl::cholesky(l, uplo, a) - } - - fn inv_cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()> { - use cholesky::*; - InvCholeskyImpl::inv_cholesky(l, uplo, a) - } - - fn solve_cholesky( - l: MatrixLayout, - uplo: UPLO, - a: &[Self], - b: &mut [Self], - ) -> Result<()> { - use cholesky::*; - SolveCholeskyImpl::solve_cholesky(l, uplo, a, b) - } - - fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result { - use rcond::*; - let mut work = RcondWork::<$s>::new(l); - work.calc(a, anorm) - } - - fn opnorm(t: NormType, l: MatrixLayout, a: &[Self]) -> Self::Real { - use opnorm::*; - let mut work = OperatorNormWork::<$s>::new(t, l); - work.calc(a) - } - - fn solve_triangular( - al: MatrixLayout, - bl: MatrixLayout, - uplo: UPLO, - d: Diag, - a: &[Self], - b: &mut [Self], - ) -> Result<()> { - use triangular::*; - SolveTriangularImpl::solve_triangular(al, bl, uplo, d, a, b) - } - - fn lu_tridiagonal(a: Tridiagonal) -> Result> { - use tridiagonal::*; - let work = LuTridiagonalWork::<$s>::new(a.l); - work.eval(a) - } - - fn rcond_tridiagonal(lu: &LUFactorizedTridiagonal) -> Result { - use tridiagonal::*; - let mut work = RcondTridiagonalWork::<$s>::new(lu.a.l); - work.calc(lu) - } - - fn solve_tridiagonal( - lu: &LUFactorizedTridiagonal, - bl: MatrixLayout, - t: Transpose, - b: &mut [Self], - ) -> Result<()> { - use tridiagonal::*; - SolveTridiagonalImpl::solve_tridiagonal(lu, bl, t, b) - } - } - }; -} -impl_lapack!(c64); -impl_lapack!(c32); -impl_lapack!(f64); -impl_lapack!(f32); diff --git a/lax/src/opnorm.rs b/lax/src/opnorm.rs deleted file mode 100644 index 1789f385..00000000 --- a/lax/src/opnorm.rs +++ /dev/null @@ -1,58 +0,0 @@ -//! Operator norm - -use super::{AsPtr, NormType}; -use crate::{layout::MatrixLayout, *}; -use cauchy::*; - -pub struct OperatorNormWork { - pub ty: NormType, - pub layout: MatrixLayout, - pub work: Vec>, -} - -pub trait OperatorNormWorkImpl { - type Elem: Scalar; - fn new(t: NormType, l: MatrixLayout) -> Self; - fn calc(&mut self, a: &[Self::Elem]) -> ::Real; -} - -macro_rules! impl_operator_norm { - ($s:ty, $lange:path) => { - impl OperatorNormWorkImpl for OperatorNormWork<$s> { - type Elem = $s; - - fn new(ty: NormType, layout: MatrixLayout) -> Self { - let m = layout.lda(); - let work = match (ty, layout) { - (NormType::Infinity, MatrixLayout::F { .. }) - | (NormType::One, MatrixLayout::C { .. }) => vec_uninit(m as usize), - _ => Vec::new(), - }; - OperatorNormWork { ty, layout, work } - } - - fn calc(&mut self, a: &[Self::Elem]) -> ::Real { - let m = self.layout.lda(); - let n = self.layout.len(); - let t = match self.layout { - MatrixLayout::F { .. } => self.ty, - MatrixLayout::C { .. } => self.ty.transpose(), - }; - unsafe { - $lange( - t.as_ptr(), - &m, - &n, - AsPtr::as_ptr(a), - &m, - AsPtr::as_mut_ptr(&mut self.work), - ) - } - } - } - }; -} -impl_operator_norm!(c64, lapack_sys::zlange_); -impl_operator_norm!(c32, lapack_sys::clange_); -impl_operator_norm!(f64, lapack_sys::dlange_); -impl_operator_norm!(f32, lapack_sys::slange_); diff --git a/lax/src/qr.rs b/lax/src/qr.rs deleted file mode 100644 index f37bd579..00000000 --- a/lax/src/qr.rs +++ /dev/null @@ -1,216 +0,0 @@ -//! QR decomposition - -use crate::{error::*, layout::MatrixLayout, *}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -pub struct HouseholderWork { - pub m: i32, - pub n: i32, - pub layout: MatrixLayout, - pub tau: Vec>, - pub work: Vec>, -} - -pub trait HouseholderWorkImpl: Sized { - type Elem: Scalar; - fn new(l: MatrixLayout) -> Result; - fn calc(&mut self, a: &mut [Self::Elem]) -> Result<&[Self::Elem]>; - fn eval(self, a: &mut [Self::Elem]) -> Result>; -} - -macro_rules! impl_householder_work { - ($s:ty, $qrf:path, $lqf: path) => { - impl HouseholderWorkImpl for HouseholderWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout) -> Result { - let m = layout.lda(); - let n = layout.len(); - let k = m.min(n); - let mut tau = vec_uninit(k as usize); - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - match layout { - MatrixLayout::F { .. } => unsafe { - $qrf( - &m, - &n, - std::ptr::null_mut(), - &m, - AsPtr::as_mut_ptr(&mut tau), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ) - }, - MatrixLayout::C { .. } => unsafe { - $lqf( - &m, - &n, - std::ptr::null_mut(), - &m, - AsPtr::as_mut_ptr(&mut tau), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ) - }, - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(HouseholderWork { - n, - m, - layout, - tau, - work, - }) - } - - fn calc(&mut self, a: &mut [Self::Elem]) -> Result<&[Self::Elem]> { - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - match self.layout { - MatrixLayout::F { .. } => unsafe { - $qrf( - &self.m, - &self.n, - AsPtr::as_mut_ptr(a), - &self.m, - AsPtr::as_mut_ptr(&mut self.tau), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ); - }, - MatrixLayout::C { .. } => unsafe { - $lqf( - &self.m, - &self.n, - AsPtr::as_mut_ptr(a), - &self.m, - AsPtr::as_mut_ptr(&mut self.tau), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ); - }, - } - info.as_lapack_result()?; - Ok(unsafe { self.tau.slice_assume_init_ref() }) - } - - fn eval(mut self, a: &mut [Self::Elem]) -> Result> { - let _eig = self.calc(a)?; - Ok(unsafe { self.tau.assume_init() }) - } - } - }; -} -impl_householder_work!(c64, lapack_sys::zgeqrf_, lapack_sys::zgelqf_); -impl_householder_work!(c32, lapack_sys::cgeqrf_, lapack_sys::cgelqf_); -impl_householder_work!(f64, lapack_sys::dgeqrf_, lapack_sys::dgelqf_); -impl_householder_work!(f32, lapack_sys::sgeqrf_, lapack_sys::sgelqf_); - -pub struct QWork { - pub layout: MatrixLayout, - pub work: Vec>, -} - -pub trait QWorkImpl: Sized { - type Elem: Scalar; - fn new(layout: MatrixLayout) -> Result; - fn calc(&mut self, a: &mut [Self::Elem], tau: &[Self::Elem]) -> Result<()>; -} - -macro_rules! impl_q_work { - ($s:ty, $gqr:path, $glq:path) => { - impl QWorkImpl for QWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout) -> Result { - let m = layout.lda(); - let n = layout.len(); - let k = m.min(n); - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - match layout { - MatrixLayout::F { .. } => unsafe { - $gqr( - &m, - &k, - &k, - std::ptr::null_mut(), - &m, - std::ptr::null_mut(), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ) - }, - MatrixLayout::C { .. } => unsafe { - $glq( - &k, - &n, - &k, - std::ptr::null_mut(), - &m, - std::ptr::null_mut(), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ) - }, - } - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(QWork { layout, work }) - } - - fn calc(&mut self, a: &mut [Self::Elem], tau: &[Self::Elem]) -> Result<()> { - let m = self.layout.lda(); - let n = self.layout.len(); - let k = m.min(n); - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - match self.layout { - MatrixLayout::F { .. } => unsafe { - $gqr( - &m, - &k, - &k, - AsPtr::as_mut_ptr(a), - &m, - AsPtr::as_ptr(&tau), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ) - }, - MatrixLayout::C { .. } => unsafe { - $glq( - &k, - &n, - &k, - AsPtr::as_mut_ptr(a), - &m, - AsPtr::as_ptr(&tau), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ) - }, - } - info.as_lapack_result()?; - Ok(()) - } - } - }; -} - -impl_q_work!(c64, lapack_sys::zungqr_, lapack_sys::zunglq_); -impl_q_work!(c32, lapack_sys::cungqr_, lapack_sys::cunglq_); -impl_q_work!(f64, lapack_sys::dorgqr_, lapack_sys::dorglq_); -impl_q_work!(f32, lapack_sys::sorgqr_, lapack_sys::sorglq_); diff --git a/lax/src/rcond.rs b/lax/src/rcond.rs deleted file mode 100644 index 4d4a4c92..00000000 --- a/lax/src/rcond.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! Reciprocal conditional number - -use crate::{error::*, layout::MatrixLayout, *}; -use cauchy::*; -use num_traits::Zero; - -pub struct RcondWork { - pub layout: MatrixLayout, - pub work: Vec>, - pub rwork: Option>>, - pub iwork: Option>>, -} - -pub trait RcondWorkImpl { - type Elem: Scalar; - fn new(l: MatrixLayout) -> Self; - fn calc( - &mut self, - a: &[Self::Elem], - anorm: ::Real, - ) -> Result<::Real>; -} - -macro_rules! impl_rcond_work_c { - ($c:ty, $con:path) => { - impl RcondWorkImpl for RcondWork<$c> { - type Elem = $c; - - fn new(layout: MatrixLayout) -> Self { - let (n, _) = layout.size(); - let work = vec_uninit(2 * n as usize); - let rwork = vec_uninit(2 * n as usize); - RcondWork { - layout, - work, - rwork: Some(rwork), - iwork: None, - } - } - - fn calc( - &mut self, - a: &[Self::Elem], - anorm: ::Real, - ) -> Result<::Real> { - let (n, _) = self.layout.size(); - let mut rcond = ::Real::zero(); - let mut info = 0; - let norm_type = match self.layout { - MatrixLayout::C { .. } => NormType::Infinity, - MatrixLayout::F { .. } => NormType::One, - }; - unsafe { - $con( - norm_type.as_ptr(), - &n, - AsPtr::as_ptr(a), - &self.layout.lda(), - &anorm, - &mut rcond, - AsPtr::as_mut_ptr(&mut self.work), - AsPtr::as_mut_ptr(self.rwork.as_mut().unwrap()), - &mut info, - ) - }; - info.as_lapack_result()?; - Ok(rcond) - } - } - }; -} -impl_rcond_work_c!(c64, lapack_sys::zgecon_); -impl_rcond_work_c!(c32, lapack_sys::cgecon_); - -macro_rules! impl_rcond_work_r { - ($r:ty, $con:path) => { - impl RcondWorkImpl for RcondWork<$r> { - type Elem = $r; - - fn new(layout: MatrixLayout) -> Self { - let (n, _) = layout.size(); - let work = vec_uninit(4 * n as usize); - let iwork = vec_uninit(n as usize); - RcondWork { - layout, - work, - rwork: None, - iwork: Some(iwork), - } - } - - fn calc( - &mut self, - a: &[Self::Elem], - anorm: ::Real, - ) -> Result<::Real> { - let (n, _) = self.layout.size(); - let mut rcond = ::Real::zero(); - let mut info = 0; - let norm_type = match self.layout { - MatrixLayout::C { .. } => NormType::Infinity, - MatrixLayout::F { .. } => NormType::One, - }; - unsafe { - $con( - norm_type.as_ptr(), - &n, - AsPtr::as_ptr(a), - &self.layout.lda(), - &anorm, - &mut rcond, - AsPtr::as_mut_ptr(&mut self.work), - AsPtr::as_mut_ptr(self.iwork.as_mut().unwrap()), - &mut info, - ) - }; - info.as_lapack_result()?; - Ok(rcond) - } - } - }; -} -impl_rcond_work_r!(f64, lapack_sys::dgecon_); -impl_rcond_work_r!(f32, lapack_sys::sgecon_); diff --git a/lax/src/solve.rs b/lax/src/solve.rs deleted file mode 100644 index 63f69983..00000000 --- a/lax/src/solve.rs +++ /dev/null @@ -1,224 +0,0 @@ -//! Solve linear equations using LU-decomposition - -use crate::{error::*, layout::MatrixLayout, *}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -/// Helper trait to abstract `*getrf` LAPACK routines for implementing [Lapack::lu] -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | sgetrf | dgetrf | cgetrf | zgetrf | -/// -pub trait LuImpl: Scalar { - fn lu(l: MatrixLayout, a: &mut [Self]) -> Result; -} - -macro_rules! impl_lu { - ($scalar:ty, $getrf:path) => { - impl LuImpl for $scalar { - fn lu(l: MatrixLayout, a: &mut [Self]) -> Result { - let (row, col) = l.size(); - assert_eq!(a.len() as i32, row * col); - if row == 0 || col == 0 { - // Do nothing for empty matrix - return Ok(Vec::new()); - } - let k = ::std::cmp::min(row, col); - let mut ipiv = vec_uninit(k as usize); - let mut info = 0; - unsafe { - $getrf( - &l.lda(), - &l.len(), - AsPtr::as_mut_ptr(a), - &l.lda(), - AsPtr::as_mut_ptr(&mut ipiv), - &mut info, - ) - }; - info.as_lapack_result()?; - let ipiv = unsafe { ipiv.assume_init() }; - Ok(ipiv) - } - } - }; -} - -impl_lu!(c64, lapack_sys::zgetrf_); -impl_lu!(c32, lapack_sys::cgetrf_); -impl_lu!(f64, lapack_sys::dgetrf_); -impl_lu!(f32, lapack_sys::sgetrf_); - -#[cfg_attr(doc, katexit::katexit)] -/// Helper trait to abstract `*getrs` LAPACK routines for implementing [Lapack::solve] -/// -/// If the array has C layout, then it needs to be handled -/// specially, since LAPACK expects a Fortran-layout array. -/// Reinterpreting a C layout array as Fortran layout is -/// equivalent to transposing it. So, we can handle the "no -/// transpose" and "transpose" cases by swapping to "transpose" -/// or "no transpose", respectively. For the "Hermite" case, we -/// can take advantage of the following: -/// -/// $$ -/// \begin{align*} -/// A^H x &= b \\\\ -/// \Leftrightarrow \overline{A^T} x &= b \\\\ -/// \Leftrightarrow \overline{\overline{A^T} x} &= \overline{b} \\\\ -/// \Leftrightarrow \overline{\overline{A^T}} \overline{x} &= \overline{b} \\\\ -/// \Leftrightarrow A^T \overline{x} &= \overline{b} -/// \end{align*} -/// $$ -/// -/// So, we can handle this case by switching to "no transpose" -/// (which is equivalent to transposing the array since it will -/// be reinterpreted as Fortran layout) and applying the -/// elementwise conjugate to `x` and `b`. -/// -pub trait SolveImpl: Scalar { - /// LAPACK correspondance - /// ---------------------- - /// - /// | f32 | f64 | c32 | c64 | - /// |:-------|:-------|:-------|:-------| - /// | sgetrs | dgetrs | cgetrs | zgetrs | - /// - fn solve(l: MatrixLayout, t: Transpose, a: &[Self], p: &Pivot, b: &mut [Self]) -> Result<()>; -} - -macro_rules! impl_solve { - ($scalar:ty, $getrs:path) => { - impl SolveImpl for $scalar { - fn solve( - l: MatrixLayout, - t: Transpose, - a: &[Self], - ipiv: &Pivot, - b: &mut [Self], - ) -> Result<()> { - let (t, conj) = match l { - MatrixLayout::C { .. } => match t { - Transpose::No => (Transpose::Transpose, false), - Transpose::Transpose => (Transpose::No, false), - Transpose::Hermite => (Transpose::No, true), - }, - MatrixLayout::F { .. } => (t, false), - }; - let (n, _) = l.size(); - let nrhs = 1; - let ldb = l.lda(); - let mut info = 0; - if conj { - for b_elem in &mut *b { - *b_elem = b_elem.conj(); - } - } - unsafe { - $getrs( - t.as_ptr(), - &n, - &nrhs, - AsPtr::as_ptr(a), - &l.lda(), - ipiv.as_ptr(), - AsPtr::as_mut_ptr(b), - &ldb, - &mut info, - ) - }; - if conj { - for b_elem in &mut *b { - *b_elem = b_elem.conj(); - } - } - info.as_lapack_result()?; - Ok(()) - } - } - }; -} // impl_solve! - -impl_solve!(f64, lapack_sys::dgetrs_); -impl_solve!(f32, lapack_sys::sgetrs_); -impl_solve!(c64, lapack_sys::zgetrs_); -impl_solve!(c32, lapack_sys::cgetrs_); - -/// Working memory for computing inverse matrix -pub struct InvWork { - pub layout: MatrixLayout, - pub work: Vec>, -} - -/// Helper trait to abstract `*getri` LAPACK rotuines for implementing [Lapack::inv] -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | sgetri | dgetri | cgetri | zgetri | -/// -pub trait InvWorkImpl: Sized { - type Elem: Scalar; - fn new(layout: MatrixLayout) -> Result; - fn calc(&mut self, a: &mut [Self::Elem], p: &Pivot) -> Result<()>; -} - -macro_rules! impl_inv_work { - ($s:ty, $tri:path) => { - impl InvWorkImpl for InvWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout) -> Result { - let (n, _) = layout.size(); - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $tri( - &n, - std::ptr::null_mut(), - &layout.lda(), - std::ptr::null(), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ) - }; - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(InvWork { layout, work }) - } - - fn calc(&mut self, a: &mut [Self::Elem], ipiv: &Pivot) -> Result<()> { - if self.layout.len() == 0 { - return Ok(()); - } - let lwork = self.work.len().to_i32().unwrap(); - let mut info = 0; - unsafe { - $tri( - &self.layout.len(), - AsPtr::as_mut_ptr(a), - &self.layout.lda(), - ipiv.as_ptr(), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ) - }; - info.as_lapack_result()?; - Ok(()) - } - } - }; -} - -impl_inv_work!(c64, lapack_sys::zgetri_); -impl_inv_work!(c32, lapack_sys::cgetri_); -impl_inv_work!(f64, lapack_sys::dgetri_); -impl_inv_work!(f32, lapack_sys::sgetri_); diff --git a/lax/src/solveh.rs b/lax/src/solveh.rs deleted file mode 100644 index abb75cb8..00000000 --- a/lax/src/solveh.rs +++ /dev/null @@ -1,199 +0,0 @@ -//! Factorize symmetric/Hermitian matrix using [Bunch-Kaufman diagonal pivoting method][BK] -//! -//! [BK]: https://doi.org/10.2307/2005787 -//! - -use crate::{error::*, layout::MatrixLayout, *}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -pub struct BkWork { - pub layout: MatrixLayout, - pub work: Vec>, - pub ipiv: Vec>, -} - -/// Factorize symmetric/Hermitian matrix using Bunch-Kaufman diagonal pivoting method -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | ssytrf | dsytrf | chetrf | zhetrf | -/// -pub trait BkWorkImpl: Sized { - type Elem: Scalar; - fn new(l: MatrixLayout) -> Result; - fn calc(&mut self, uplo: UPLO, a: &mut [Self::Elem]) -> Result<&[i32]>; - fn eval(self, uplo: UPLO, a: &mut [Self::Elem]) -> Result; -} - -macro_rules! impl_bk_work { - ($s:ty, $trf:path) => { - impl BkWorkImpl for BkWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout) -> Result { - let (n, _) = layout.size(); - let ipiv = vec_uninit(n as usize); - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $trf( - UPLO::Upper.as_ptr(), - &n, - std::ptr::null_mut(), - &layout.lda(), - std::ptr::null_mut(), - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ) - }; - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(BkWork { layout, work, ipiv }) - } - - fn calc(&mut self, uplo: UPLO, a: &mut [Self::Elem]) -> Result<&[i32]> { - let (n, _) = self.layout.size(); - let lwork = self.work.len().to_i32().unwrap(); - if lwork == 0 { - return Ok(&[]); - } - let mut info = 0; - unsafe { - $trf( - uplo.as_ptr(), - &n, - AsPtr::as_mut_ptr(a), - &self.layout.lda(), - AsPtr::as_mut_ptr(&mut self.ipiv), - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - &mut info, - ) - }; - info.as_lapack_result()?; - Ok(unsafe { self.ipiv.slice_assume_init_ref() }) - } - - fn eval(mut self, uplo: UPLO, a: &mut [Self::Elem]) -> Result { - let _ref = self.calc(uplo, a)?; - Ok(unsafe { self.ipiv.assume_init() }) - } - } - }; -} -impl_bk_work!(c64, lapack_sys::zhetrf_); -impl_bk_work!(c32, lapack_sys::chetrf_); -impl_bk_work!(f64, lapack_sys::dsytrf_); -impl_bk_work!(f32, lapack_sys::ssytrf_); - -pub struct InvhWork { - pub layout: MatrixLayout, - pub work: Vec>, -} - -/// Compute inverse matrix of symmetric/Hermitian matrix -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | ssytri | dsytri | chetri | zhetri | -/// -pub trait InvhWorkImpl: Sized { - type Elem; - fn new(layout: MatrixLayout) -> Result; - fn calc(&mut self, uplo: UPLO, a: &mut [Self::Elem], ipiv: &Pivot) -> Result<()>; -} - -macro_rules! impl_invh_work { - ($s:ty, $tri:path) => { - impl InvhWorkImpl for InvhWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout) -> Result { - let (n, _) = layout.size(); - let work = vec_uninit(n as usize); - Ok(InvhWork { layout, work }) - } - - fn calc(&mut self, uplo: UPLO, a: &mut [Self::Elem], ipiv: &Pivot) -> Result<()> { - let (n, _) = self.layout.size(); - let mut info = 0; - unsafe { - $tri( - uplo.as_ptr(), - &n, - AsPtr::as_mut_ptr(a), - &self.layout.lda(), - ipiv.as_ptr(), - AsPtr::as_mut_ptr(&mut self.work), - &mut info, - ) - }; - info.as_lapack_result()?; - Ok(()) - } - } - }; -} -impl_invh_work!(c64, lapack_sys::zhetri_); -impl_invh_work!(c32, lapack_sys::chetri_); -impl_invh_work!(f64, lapack_sys::dsytri_); -impl_invh_work!(f32, lapack_sys::ssytri_); - -/// Solve symmetric/Hermitian linear equation -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | ssytrs | dsytrs | chetrs | zhetrs | -/// -pub trait SolvehImpl: Scalar { - fn solveh(l: MatrixLayout, uplo: UPLO, a: &[Self], ipiv: &Pivot, b: &mut [Self]) -> Result<()>; -} - -macro_rules! impl_solveh_ { - ($s:ty, $trs:path) => { - impl SolvehImpl for $s { - fn solveh( - l: MatrixLayout, - uplo: UPLO, - a: &[Self], - ipiv: &Pivot, - b: &mut [Self], - ) -> Result<()> { - let (n, _) = l.size(); - let mut info = 0; - unsafe { - $trs( - uplo.as_ptr(), - &n, - &1, - AsPtr::as_ptr(a), - &l.lda(), - ipiv.as_ptr(), - AsPtr::as_mut_ptr(b), - &n, - &mut info, - ) - }; - info.as_lapack_result()?; - Ok(()) - } - } - }; -} - -impl_solveh_!(c64, lapack_sys::zhetrs_); -impl_solveh_!(c32, lapack_sys::chetrs_); -impl_solveh_!(f64, lapack_sys::dsytrs_); -impl_solveh_!(f32, lapack_sys::ssytrs_); diff --git a/lax/src/svd.rs b/lax/src/svd.rs deleted file mode 100644 index fc695108..00000000 --- a/lax/src/svd.rs +++ /dev/null @@ -1,314 +0,0 @@ -//! Singular-value decomposition -//! -//! LAPACK correspondance -//! ---------------------- -//! -//! | f32 | f64 | c32 | c64 | -//! |:-------|:-------|:-------|:-------| -//! | sgesvd | dgesvd | cgesvd | zgesvd | -//! - -use super::{error::*, layout::*, *}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -pub struct SvdWork { - pub ju: JobSvd, - pub jvt: JobSvd, - pub layout: MatrixLayout, - pub s: Vec>, - pub u: Option>>, - pub vt: Option>>, - pub work: Vec>, - pub rwork: Option>>, -} - -#[derive(Debug, Clone)] -pub struct SvdRef<'work, T: Scalar> { - pub s: &'work [T::Real], - pub u: Option<&'work [T]>, - pub vt: Option<&'work [T]>, -} - -#[derive(Debug, Clone)] -pub struct SvdOwned { - pub s: Vec, - pub u: Option>, - pub vt: Option>, -} - -pub trait SvdWorkImpl: Sized { - type Elem: Scalar; - fn new(layout: MatrixLayout, calc_u: bool, calc_vt: bool) -> Result; - fn calc(&mut self, a: &mut [Self::Elem]) -> Result>; - fn eval(self, a: &mut [Self::Elem]) -> Result>; -} - -macro_rules! impl_svd_work_c { - ($s:ty, $svd:path) => { - impl SvdWorkImpl for SvdWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout, calc_u: bool, calc_vt: bool) -> Result { - let ju = match layout { - MatrixLayout::F { .. } => JobSvd::from_bool(calc_u), - MatrixLayout::C { .. } => JobSvd::from_bool(calc_vt), - }; - let jvt = match layout { - MatrixLayout::F { .. } => JobSvd::from_bool(calc_vt), - MatrixLayout::C { .. } => JobSvd::from_bool(calc_u), - }; - - let m = layout.lda(); - let mut u = match ju { - JobSvd::All => Some(vec_uninit((m * m) as usize)), - JobSvd::None => None, - _ => unimplemented!("SVD with partial vector output is not supported yet"), - }; - - let n = layout.len(); - let mut vt = match jvt { - JobSvd::All => Some(vec_uninit((n * n) as usize)), - JobSvd::None => None, - _ => unimplemented!("SVD with partial vector output is not supported yet"), - }; - - let k = std::cmp::min(m, n); - let mut s = vec_uninit(k as usize); - let mut rwork = vec_uninit(5 * k as usize); - - // eval work size - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $svd( - ju.as_ptr(), - jvt.as_ptr(), - &m, - &n, - std::ptr::null_mut(), - &m, - AsPtr::as_mut_ptr(&mut s), - AsPtr::as_mut_ptr(u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])), - &m, - AsPtr::as_mut_ptr(vt.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - AsPtr::as_mut_ptr(&mut rwork), - &mut info, - ); - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(SvdWork { - layout, - ju, - jvt, - s, - u, - vt, - work, - rwork: Some(rwork), - }) - } - - fn calc(&mut self, a: &mut [Self::Elem]) -> Result> { - let m = self.layout.lda(); - let n = self.layout.len(); - let lwork = self.work.len().to_i32().unwrap(); - - let mut info = 0; - unsafe { - $svd( - self.ju.as_ptr(), - self.jvt.as_ptr(), - &m, - &n, - AsPtr::as_mut_ptr(a), - &m, - AsPtr::as_mut_ptr(&mut self.s), - AsPtr::as_mut_ptr( - self.u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut []), - ), - &m, - AsPtr::as_mut_ptr( - self.vt - .as_mut() - .map(|x| x.as_mut_slice()) - .unwrap_or(&mut []), - ), - &n, - AsPtr::as_mut_ptr(&mut self.work), - &(lwork as i32), - AsPtr::as_mut_ptr(self.rwork.as_mut().unwrap()), - &mut info, - ); - } - info.as_lapack_result()?; - - let s = unsafe { self.s.slice_assume_init_ref() }; - let u = self - .u - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }); - let vt = self - .vt - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }); - - match self.layout { - MatrixLayout::F { .. } => Ok(SvdRef { s, u, vt }), - MatrixLayout::C { .. } => Ok(SvdRef { s, u: vt, vt: u }), - } - } - - fn eval(mut self, a: &mut [Self::Elem]) -> Result> { - let _ref = self.calc(a)?; - let s = unsafe { self.s.assume_init() }; - let u = self.u.map(|v| unsafe { v.assume_init() }); - let vt = self.vt.map(|v| unsafe { v.assume_init() }); - match self.layout { - MatrixLayout::F { .. } => Ok(SvdOwned { s, u, vt }), - MatrixLayout::C { .. } => Ok(SvdOwned { s, u: vt, vt: u }), - } - } - } - }; -} -impl_svd_work_c!(c64, lapack_sys::zgesvd_); -impl_svd_work_c!(c32, lapack_sys::cgesvd_); - -macro_rules! impl_svd_work_r { - ($s:ty, $svd:path) => { - impl SvdWorkImpl for SvdWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout, calc_u: bool, calc_vt: bool) -> Result { - let ju = match layout { - MatrixLayout::F { .. } => JobSvd::from_bool(calc_u), - MatrixLayout::C { .. } => JobSvd::from_bool(calc_vt), - }; - let jvt = match layout { - MatrixLayout::F { .. } => JobSvd::from_bool(calc_vt), - MatrixLayout::C { .. } => JobSvd::from_bool(calc_u), - }; - - let m = layout.lda(); - let mut u = match ju { - JobSvd::All => Some(vec_uninit((m * m) as usize)), - JobSvd::None => None, - _ => unimplemented!("SVD with partial vector output is not supported yet"), - }; - - let n = layout.len(); - let mut vt = match jvt { - JobSvd::All => Some(vec_uninit((n * n) as usize)), - JobSvd::None => None, - _ => unimplemented!("SVD with partial vector output is not supported yet"), - }; - - let k = std::cmp::min(m, n); - let mut s = vec_uninit(k as usize); - - // eval work size - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $svd( - ju.as_ptr(), - jvt.as_ptr(), - &m, - &n, - std::ptr::null_mut(), - &m, - AsPtr::as_mut_ptr(&mut s), - AsPtr::as_mut_ptr(u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])), - &m, - AsPtr::as_mut_ptr(vt.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])), - &n, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - &mut info, - ); - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(SvdWork { - layout, - ju, - jvt, - s, - u, - vt, - work, - rwork: None, - }) - } - - fn calc(&mut self, a: &mut [Self::Elem]) -> Result> { - let m = self.layout.lda(); - let n = self.layout.len(); - let lwork = self.work.len().to_i32().unwrap(); - - let mut info = 0; - unsafe { - $svd( - self.ju.as_ptr(), - self.jvt.as_ptr(), - &m, - &n, - AsPtr::as_mut_ptr(a), - &m, - AsPtr::as_mut_ptr(&mut self.s), - AsPtr::as_mut_ptr( - self.u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut []), - ), - &m, - AsPtr::as_mut_ptr( - self.vt - .as_mut() - .map(|x| x.as_mut_slice()) - .unwrap_or(&mut []), - ), - &n, - AsPtr::as_mut_ptr(&mut self.work), - &(lwork as i32), - &mut info, - ); - } - info.as_lapack_result()?; - - let s = unsafe { self.s.slice_assume_init_ref() }; - let u = self - .u - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }); - let vt = self - .vt - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }); - - match self.layout { - MatrixLayout::F { .. } => Ok(SvdRef { s, u, vt }), - MatrixLayout::C { .. } => Ok(SvdRef { s, u: vt, vt: u }), - } - } - - fn eval(mut self, a: &mut [Self::Elem]) -> Result> { - let _ref = self.calc(a)?; - let s = unsafe { self.s.assume_init() }; - let u = self.u.map(|v| unsafe { v.assume_init() }); - let vt = self.vt.map(|v| unsafe { v.assume_init() }); - match self.layout { - MatrixLayout::F { .. } => Ok(SvdOwned { s, u, vt }), - MatrixLayout::C { .. } => Ok(SvdOwned { s, u: vt, vt: u }), - } - } - } - }; -} -impl_svd_work_r!(f64, lapack_sys::dgesvd_); -impl_svd_work_r!(f32, lapack_sys::sgesvd_); diff --git a/lax/src/svddc.rs b/lax/src/svddc.rs deleted file mode 100644 index c16db4bb..00000000 --- a/lax/src/svddc.rs +++ /dev/null @@ -1,307 +0,0 @@ -//! Compute singular value decomposition with divide-and-conquer algorithm -//! -//! LAPACK correspondance -//! ---------------------- -//! -//! | f32 | f64 | c32 | c64 | -//! |:-------|:-------|:-------|:-------| -//! | sgesdd | dgesdd | cgesdd | zgesdd | -//! - -use crate::{error::*, layout::MatrixLayout, *}; -use cauchy::*; -use num_traits::{ToPrimitive, Zero}; - -pub struct SvdDcWork { - pub jobz: JobSvd, - pub layout: MatrixLayout, - pub s: Vec>, - pub u: Option>>, - pub vt: Option>>, - pub work: Vec>, - pub iwork: Vec>, - pub rwork: Option>>, -} - -pub trait SvdDcWorkImpl: Sized { - type Elem: Scalar; - fn new(layout: MatrixLayout, jobz: JobSvd) -> Result; - fn calc(&mut self, a: &mut [Self::Elem]) -> Result>; - fn eval(self, a: &mut [Self::Elem]) -> Result>; -} - -macro_rules! impl_svd_dc_work_c { - ($s:ty, $sdd:path) => { - impl SvdDcWorkImpl for SvdDcWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout, jobz: JobSvd) -> Result { - let m = layout.lda(); - let n = layout.len(); - let k = m.min(n); - let (u_col, vt_row) = match jobz { - JobSvd::All | JobSvd::None => (m, n), - JobSvd::Some => (k, k), - }; - - let mut s = vec_uninit(k as usize); - let (mut u, mut vt) = match jobz { - JobSvd::All => ( - Some(vec_uninit((m * m) as usize)), - Some(vec_uninit((n * n) as usize)), - ), - JobSvd::Some => ( - Some(vec_uninit((m * u_col) as usize)), - Some(vec_uninit((n * vt_row) as usize)), - ), - JobSvd::None => (None, None), - }; - let mut iwork = vec_uninit(8 * k as usize); - - let mx = n.max(m) as usize; - let mn = n.min(m) as usize; - let lrwork = match jobz { - JobSvd::None => 7 * mn, - _ => std::cmp::max(5 * mn * mn + 5 * mn, 2 * mx * mn + 2 * mn * mn + mn), - }; - let mut rwork = vec_uninit(lrwork); - - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $sdd( - jobz.as_ptr(), - &m, - &n, - std::ptr::null_mut(), - &m, - AsPtr::as_mut_ptr(&mut s), - AsPtr::as_mut_ptr(u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])), - &m, - AsPtr::as_mut_ptr(vt.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])), - &vt_row, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - AsPtr::as_mut_ptr(&mut rwork), - AsPtr::as_mut_ptr(&mut iwork), - &mut info, - ); - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(SvdDcWork { - layout, - jobz, - iwork, - work, - rwork: Some(rwork), - u, - vt, - s, - }) - } - - fn calc(&mut self, a: &mut [Self::Elem]) -> Result> { - let m = self.layout.lda(); - let n = self.layout.len(); - let k = m.min(n); - let (_, vt_row) = match self.jobz { - JobSvd::All | JobSvd::None => (m, n), - JobSvd::Some => (k, k), - }; - let lwork = self.work.len().to_i32().unwrap(); - - let mut info = 0; - unsafe { - $sdd( - self.jobz.as_ptr(), - &m, - &n, - AsPtr::as_mut_ptr(a), - &m, - AsPtr::as_mut_ptr(&mut self.s), - AsPtr::as_mut_ptr( - self.u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut []), - ), - &m, - AsPtr::as_mut_ptr( - self.vt - .as_mut() - .map(|x| x.as_mut_slice()) - .unwrap_or(&mut []), - ), - &vt_row, - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - AsPtr::as_mut_ptr(self.rwork.as_mut().unwrap()), - AsPtr::as_mut_ptr(&mut self.iwork), - &mut info, - ); - } - info.as_lapack_result()?; - - let s = unsafe { self.s.slice_assume_init_ref() }; - let u = self - .u - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }); - let vt = self - .vt - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }); - - Ok(match self.layout { - MatrixLayout::F { .. } => SvdRef { s, u, vt }, - MatrixLayout::C { .. } => SvdRef { s, u: vt, vt: u }, - }) - } - - fn eval(mut self, a: &mut [Self::Elem]) -> Result> { - let _ref = self.calc(a)?; - let s = unsafe { self.s.assume_init() }; - let u = self.u.map(|v| unsafe { v.assume_init() }); - let vt = self.vt.map(|v| unsafe { v.assume_init() }); - Ok(match self.layout { - MatrixLayout::F { .. } => SvdOwned { s, u, vt }, - MatrixLayout::C { .. } => SvdOwned { s, u: vt, vt: u }, - }) - } - } - }; -} -impl_svd_dc_work_c!(c64, lapack_sys::zgesdd_); -impl_svd_dc_work_c!(c32, lapack_sys::cgesdd_); - -macro_rules! impl_svd_dc_work_r { - ($s:ty, $sdd:path) => { - impl SvdDcWorkImpl for SvdDcWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout, jobz: JobSvd) -> Result { - let m = layout.lda(); - let n = layout.len(); - let k = m.min(n); - let (u_col, vt_row) = match jobz { - JobSvd::All | JobSvd::None => (m, n), - JobSvd::Some => (k, k), - }; - - let mut s = vec_uninit(k as usize); - let (mut u, mut vt) = match jobz { - JobSvd::All => ( - Some(vec_uninit((m * m) as usize)), - Some(vec_uninit((n * n) as usize)), - ), - JobSvd::Some => ( - Some(vec_uninit((m * u_col) as usize)), - Some(vec_uninit((n * vt_row) as usize)), - ), - JobSvd::None => (None, None), - }; - let mut iwork = vec_uninit(8 * k as usize); - - let mut info = 0; - let mut work_size = [Self::Elem::zero()]; - unsafe { - $sdd( - jobz.as_ptr(), - &m, - &n, - std::ptr::null_mut(), - &m, - AsPtr::as_mut_ptr(&mut s), - AsPtr::as_mut_ptr(u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])), - &m, - AsPtr::as_mut_ptr(vt.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])), - &vt_row, - AsPtr::as_mut_ptr(&mut work_size), - &(-1), - AsPtr::as_mut_ptr(&mut iwork), - &mut info, - ); - } - info.as_lapack_result()?; - let lwork = work_size[0].to_usize().unwrap(); - let work = vec_uninit(lwork); - Ok(SvdDcWork { - layout, - jobz, - iwork, - work, - rwork: None, - u, - vt, - s, - }) - } - - fn calc(&mut self, a: &mut [Self::Elem]) -> Result> { - let m = self.layout.lda(); - let n = self.layout.len(); - let k = m.min(n); - let (_, vt_row) = match self.jobz { - JobSvd::All | JobSvd::None => (m, n), - JobSvd::Some => (k, k), - }; - let lwork = self.work.len().to_i32().unwrap(); - - let mut info = 0; - unsafe { - $sdd( - self.jobz.as_ptr(), - &m, - &n, - AsPtr::as_mut_ptr(a), - &m, - AsPtr::as_mut_ptr(&mut self.s), - AsPtr::as_mut_ptr( - self.u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut []), - ), - &m, - AsPtr::as_mut_ptr( - self.vt - .as_mut() - .map(|x| x.as_mut_slice()) - .unwrap_or(&mut []), - ), - &vt_row, - AsPtr::as_mut_ptr(&mut self.work), - &lwork, - AsPtr::as_mut_ptr(&mut self.iwork), - &mut info, - ); - } - info.as_lapack_result()?; - - let s = unsafe { self.s.slice_assume_init_ref() }; - let u = self - .u - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }); - let vt = self - .vt - .as_ref() - .map(|v| unsafe { v.slice_assume_init_ref() }); - - Ok(match self.layout { - MatrixLayout::F { .. } => SvdRef { s, u, vt }, - MatrixLayout::C { .. } => SvdRef { s, u: vt, vt: u }, - }) - } - - fn eval(mut self, a: &mut [Self::Elem]) -> Result> { - let _ref = self.calc(a)?; - let s = unsafe { self.s.assume_init() }; - let u = self.u.map(|v| unsafe { v.assume_init() }); - let vt = self.vt.map(|v| unsafe { v.assume_init() }); - Ok(match self.layout { - MatrixLayout::F { .. } => SvdOwned { s, u, vt }, - MatrixLayout::C { .. } => SvdOwned { s, u: vt, vt: u }, - }) - } - } - }; -} -impl_svd_dc_work_r!(f64, lapack_sys::dgesdd_); -impl_svd_dc_work_r!(f32, lapack_sys::sgesdd_); diff --git a/lax/src/triangular.rs b/lax/src/triangular.rs deleted file mode 100644 index da4dc4cf..00000000 --- a/lax/src/triangular.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! Linear problem for triangular matrices - -use crate::{error::*, layout::*, *}; -use cauchy::*; - -/// Solve linear problem for triangular matrices -/// -/// LAPACK correspondance -/// ---------------------- -/// -/// | f32 | f64 | c32 | c64 | -/// |:-------|:-------|:-------|:-------| -/// | strtrs | dtrtrs | ctrtrs | ztrtrs | -/// -pub trait SolveTriangularImpl: Scalar { - fn solve_triangular( - al: MatrixLayout, - bl: MatrixLayout, - uplo: UPLO, - d: Diag, - a: &[Self], - b: &mut [Self], - ) -> Result<()>; -} - -macro_rules! impl_triangular { - ($scalar:ty, $trtrs:path) => { - impl SolveTriangularImpl for $scalar { - fn solve_triangular( - a_layout: MatrixLayout, - b_layout: MatrixLayout, - uplo: UPLO, - diag: Diag, - a: &[Self], - b: &mut [Self], - ) -> Result<()> { - // Transpose if a is C-continuous - let mut a_t = None; - let a_layout = match a_layout { - MatrixLayout::C { .. } => { - let (layout, t) = transpose(a_layout, a); - a_t = Some(t); - layout - } - MatrixLayout::F { .. } => a_layout, - }; - - // Transpose if b is C-continuous - let mut b_t = None; - let b_layout = match b_layout { - MatrixLayout::C { .. } => { - let (layout, t) = transpose(b_layout, b); - b_t = Some(t); - layout - } - MatrixLayout::F { .. } => b_layout, - }; - - let (m, n) = a_layout.size(); - let (n_, nrhs) = b_layout.size(); - assert_eq!(n, n_); - - let mut info = 0; - unsafe { - $trtrs( - uplo.as_ptr(), - Transpose::No.as_ptr(), - diag.as_ptr(), - &m, - &nrhs, - AsPtr::as_ptr(a_t.as_ref().map(|v| v.as_slice()).unwrap_or(a)), - &a_layout.lda(), - AsPtr::as_mut_ptr(b_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(b)), - &b_layout.lda(), - &mut info, - ); - } - info.as_lapack_result()?; - - // Re-transpose b - if let Some(b_t) = b_t { - transpose_over(b_layout, &b_t, b); - } - Ok(()) - } - } - }; -} // impl_triangular! - -impl_triangular!(f64, lapack_sys::dtrtrs_); -impl_triangular!(f32, lapack_sys::strtrs_); -impl_triangular!(c64, lapack_sys::ztrtrs_); -impl_triangular!(c32, lapack_sys::ctrtrs_); diff --git a/lax/src/tridiagonal/lu.rs b/lax/src/tridiagonal/lu.rs deleted file mode 100644 index e159bec6..00000000 --- a/lax/src/tridiagonal/lu.rs +++ /dev/null @@ -1,101 +0,0 @@ -use crate::*; -use cauchy::*; -use num_traits::Zero; - -/// Represents the LU factorization of a tridiagonal matrix `A` as `A = P*L*U`. -#[derive(Clone, PartialEq)] -pub struct LUFactorizedTridiagonal { - /// A tridiagonal matrix which consists of - /// - l : layout of raw matrix - /// - dl: (n-1) multipliers that define the matrix L. - /// - d : (n) diagonal elements of the upper triangular matrix U. - /// - du: (n-1) elements of the first super-diagonal of U. - pub a: Tridiagonal, - /// (n-2) elements of the second super-diagonal of U. - pub du2: Vec, - /// The pivot indices that define the permutation matrix `P`. - pub ipiv: Pivot, - - pub a_opnorm_one: A::Real, -} - -impl Tridiagonal { - fn opnorm_one(&self) -> A::Real { - let mut col_sum: Vec = self.d.iter().map(|val| val.abs()).collect(); - for i in 0..col_sum.len() { - if i < self.dl.len() { - col_sum[i] += self.dl[i].abs(); - } - if i > 0 { - col_sum[i] += self.du[i - 1].abs(); - } - } - let mut max = A::Real::zero(); - for &val in &col_sum { - if max < val { - max = val; - } - } - max - } -} - -pub struct LuTridiagonalWork { - pub layout: MatrixLayout, - pub du2: Vec>, - pub ipiv: Vec>, -} - -pub trait LuTridiagonalWorkImpl { - type Elem: Scalar; - fn new(layout: MatrixLayout) -> Self; - fn eval(self, a: Tridiagonal) -> Result>; -} - -macro_rules! impl_lu_tridiagonal_work { - ($s:ty, $trf:path) => { - impl LuTridiagonalWorkImpl for LuTridiagonalWork<$s> { - type Elem = $s; - - fn new(layout: MatrixLayout) -> Self { - let (n, _) = layout.size(); - let du2 = vec_uninit((n - 2) as usize); - let ipiv = vec_uninit(n as usize); - LuTridiagonalWork { layout, du2, ipiv } - } - - fn eval( - mut self, - mut a: Tridiagonal, - ) -> Result> { - let (n, _) = self.layout.size(); - // We have to calc one-norm before LU factorization - let a_opnorm_one = a.opnorm_one(); - let mut info = 0; - unsafe { - $trf( - &n, - AsPtr::as_mut_ptr(&mut a.dl), - AsPtr::as_mut_ptr(&mut a.d), - AsPtr::as_mut_ptr(&mut a.du), - AsPtr::as_mut_ptr(&mut self.du2), - AsPtr::as_mut_ptr(&mut self.ipiv), - &mut info, - ) - }; - info.as_lapack_result()?; - Ok(LUFactorizedTridiagonal { - a, - du2: unsafe { self.du2.assume_init() }, - ipiv: unsafe { self.ipiv.assume_init() }, - a_opnorm_one, - }) - } - } - }; -} - -impl_lu_tridiagonal_work!(c64, lapack_sys::zgttrf_); -impl_lu_tridiagonal_work!(c32, lapack_sys::cgttrf_); -impl_lu_tridiagonal_work!(f64, lapack_sys::dgttrf_); -impl_lu_tridiagonal_work!(f32, lapack_sys::sgttrf_); diff --git a/lax/src/tridiagonal/matrix.rs b/lax/src/tridiagonal/matrix.rs deleted file mode 100644 index 47401430..00000000 --- a/lax/src/tridiagonal/matrix.rs +++ /dev/null @@ -1,84 +0,0 @@ -use crate::layout::*; -use cauchy::*; -use std::ops::{Index, IndexMut}; - -/// Represents a tridiagonal matrix as 3 one-dimensional vectors. -/// -/// ```text -/// [d0, u1, 0, ..., 0, -/// l1, d1, u2, ..., -/// 0, l2, d2, -/// ... ..., u{n-1}, -/// 0, ..., l{n-1}, d{n-1},] -/// ``` -#[derive(Clone, PartialEq, Eq)] -pub struct Tridiagonal { - /// layout of raw matrix - pub l: MatrixLayout, - /// (n-1) sub-diagonal elements of matrix. - pub dl: Vec, - /// (n) diagonal elements of matrix. - pub d: Vec, - /// (n-1) super-diagonal elements of matrix. - pub du: Vec, -} - -impl Index<(i32, i32)> for Tridiagonal { - type Output = A; - #[inline] - fn index(&self, (row, col): (i32, i32)) -> &A { - let (n, _) = self.l.size(); - assert!( - std::cmp::max(row, col) < n, - "ndarray: index {:?} is out of bounds for array of shape {}", - [row, col], - n - ); - match row - col { - 0 => &self.d[row as usize], - 1 => &self.dl[col as usize], - -1 => &self.du[row as usize], - _ => panic!( - "ndarray-linalg::tridiagonal: index {:?} is not tridiagonal element", - [row, col] - ), - } - } -} - -impl Index<[i32; 2]> for Tridiagonal { - type Output = A; - #[inline] - fn index(&self, [row, col]: [i32; 2]) -> &A { - &self[(row, col)] - } -} - -impl IndexMut<(i32, i32)> for Tridiagonal { - #[inline] - fn index_mut(&mut self, (row, col): (i32, i32)) -> &mut A { - let (n, _) = self.l.size(); - assert!( - std::cmp::max(row, col) < n, - "ndarray: index {:?} is out of bounds for array of shape {}", - [row, col], - n - ); - match row - col { - 0 => &mut self.d[row as usize], - 1 => &mut self.dl[col as usize], - -1 => &mut self.du[row as usize], - _ => panic!( - "ndarray-linalg::tridiagonal: index {:?} is not tridiagonal element", - [row, col] - ), - } - } -} - -impl IndexMut<[i32; 2]> for Tridiagonal { - #[inline] - fn index_mut(&mut self, [row, col]: [i32; 2]) -> &mut A { - &mut self[(row, col)] - } -} diff --git a/lax/src/tridiagonal/mod.rs b/lax/src/tridiagonal/mod.rs deleted file mode 100644 index 834ddd8a..00000000 --- a/lax/src/tridiagonal/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! Implement linear solver using LU decomposition -//! for tridiagonal matrix - -mod lu; -mod matrix; -mod rcond; -mod solve; - -pub use lu::*; -pub use matrix::*; -pub use rcond::*; -pub use solve::*; diff --git a/lax/src/tridiagonal/rcond.rs b/lax/src/tridiagonal/rcond.rs deleted file mode 100644 index a309cae4..00000000 --- a/lax/src/tridiagonal/rcond.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::*; -use cauchy::*; -use num_traits::Zero; - -pub struct RcondTridiagonalWork { - pub work: Vec>, - pub iwork: Option>>, -} - -pub trait RcondTridiagonalWorkImpl { - type Elem: Scalar; - fn new(layout: MatrixLayout) -> Self; - fn calc( - &mut self, - lu: &LUFactorizedTridiagonal, - ) -> Result<::Real>; -} - -macro_rules! impl_rcond_tridiagonal_work_c { - ($c:ty, $gtcon:path) => { - impl RcondTridiagonalWorkImpl for RcondTridiagonalWork<$c> { - type Elem = $c; - - fn new(layout: MatrixLayout) -> Self { - let (n, _) = layout.size(); - let work = vec_uninit(2 * n as usize); - RcondTridiagonalWork { work, iwork: None } - } - - fn calc( - &mut self, - lu: &LUFactorizedTridiagonal, - ) -> Result<::Real> { - let (n, _) = lu.a.l.size(); - let ipiv = &lu.ipiv; - let mut rcond = ::Real::zero(); - let mut info = 0; - unsafe { - $gtcon( - NormType::One.as_ptr(), - &n, - AsPtr::as_ptr(&lu.a.dl), - AsPtr::as_ptr(&lu.a.d), - AsPtr::as_ptr(&lu.a.du), - AsPtr::as_ptr(&lu.du2), - ipiv.as_ptr(), - &lu.a_opnorm_one, - &mut rcond, - AsPtr::as_mut_ptr(&mut self.work), - &mut info, - ); - } - info.as_lapack_result()?; - Ok(rcond) - } - } - }; -} - -impl_rcond_tridiagonal_work_c!(c64, lapack_sys::zgtcon_); -impl_rcond_tridiagonal_work_c!(c32, lapack_sys::cgtcon_); - -macro_rules! impl_rcond_tridiagonal_work_r { - ($c:ty, $gtcon:path) => { - impl RcondTridiagonalWorkImpl for RcondTridiagonalWork<$c> { - type Elem = $c; - - fn new(layout: MatrixLayout) -> Self { - let (n, _) = layout.size(); - let work = vec_uninit(2 * n as usize); - let iwork = vec_uninit(n as usize); - RcondTridiagonalWork { - work, - iwork: Some(iwork), - } - } - - fn calc( - &mut self, - lu: &LUFactorizedTridiagonal, - ) -> Result<::Real> { - let (n, _) = lu.a.l.size(); - let mut rcond = ::Real::zero(); - let mut info = 0; - unsafe { - $gtcon( - NormType::One.as_ptr(), - &n, - AsPtr::as_ptr(&lu.a.dl), - AsPtr::as_ptr(&lu.a.d), - AsPtr::as_ptr(&lu.a.du), - AsPtr::as_ptr(&lu.du2), - AsPtr::as_ptr(&lu.ipiv), - &lu.a_opnorm_one, - &mut rcond, - AsPtr::as_mut_ptr(&mut self.work), - AsPtr::as_mut_ptr(self.iwork.as_mut().unwrap()), - &mut info, - ); - } - info.as_lapack_result()?; - Ok(rcond) - } - } - }; -} - -impl_rcond_tridiagonal_work_r!(f64, lapack_sys::dgtcon_); -impl_rcond_tridiagonal_work_r!(f32, lapack_sys::sgtcon_); diff --git a/lax/src/tridiagonal/solve.rs b/lax/src/tridiagonal/solve.rs deleted file mode 100644 index 43f7d120..00000000 --- a/lax/src/tridiagonal/solve.rs +++ /dev/null @@ -1,64 +0,0 @@ -use crate::{error::*, layout::*, *}; -use cauchy::*; - -pub trait SolveTridiagonalImpl: Scalar { - fn solve_tridiagonal( - lu: &LUFactorizedTridiagonal, - bl: MatrixLayout, - t: Transpose, - b: &mut [Self], - ) -> Result<()>; -} - -macro_rules! impl_solve_tridiagonal { - ($s:ty, $trs:path) => { - impl SolveTridiagonalImpl for $s { - fn solve_tridiagonal( - lu: &LUFactorizedTridiagonal, - b_layout: MatrixLayout, - t: Transpose, - b: &mut [Self], - ) -> Result<()> { - let (n, _) = lu.a.l.size(); - let ipiv = &lu.ipiv; - // Transpose if b is C-continuous - let mut b_t = None; - let b_layout = match b_layout { - MatrixLayout::C { .. } => { - let (layout, t) = transpose(b_layout, b); - b_t = Some(t); - layout - } - MatrixLayout::F { .. } => b_layout, - }; - let (ldb, nrhs) = b_layout.size(); - let mut info = 0; - unsafe { - $trs( - t.as_ptr(), - &n, - &nrhs, - AsPtr::as_ptr(&lu.a.dl), - AsPtr::as_ptr(&lu.a.d), - AsPtr::as_ptr(&lu.a.du), - AsPtr::as_ptr(&lu.du2), - ipiv.as_ptr(), - AsPtr::as_mut_ptr(b_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(b)), - &ldb, - &mut info, - ); - } - info.as_lapack_result()?; - if let Some(b_t) = b_t { - transpose_over(b_layout, &b_t, b); - } - Ok(()) - } - } - }; -} - -impl_solve_tridiagonal!(c64, lapack_sys::zgttrs_); -impl_solve_tridiagonal!(c32, lapack_sys::cgttrs_); -impl_solve_tridiagonal!(f64, lapack_sys::dgttrs_); -impl_solve_tridiagonal!(f32, lapack_sys::sgttrs_); diff --git a/lax/struct.LUFactorizedTridiagonal.html b/lax/struct.LUFactorizedTridiagonal.html new file mode 100644 index 00000000..aa01ddb2 --- /dev/null +++ b/lax/struct.LUFactorizedTridiagonal.html @@ -0,0 +1,60 @@ +LUFactorizedTridiagonal in lax - Rust + + + + + + +
pub struct LUFactorizedTridiagonal<A: Scalar> {
+    pub a: Tridiagonal<A>,
+    pub du2: Vec<A>,
+    pub ipiv: Pivot,
+    /* private fields */
+}
Expand description

Represents the LU factorization of a tridiagonal matrix A as A = P*L*U.

+

Fields

a: Tridiagonal<A>

A tridiagonal matrix which consists of

+
    +
  • l : layout of raw matrix
  • +
  • dl: (n-1) multipliers that define the matrix L.
  • +
  • d : (n) diagonal elements of the upper triangular matrix U.
  • +
  • du: (n-1) elements of the first super-diagonal of U.
  • +
+
du2: Vec<A>

(n-2) elements of the second super-diagonal of U.

+
ipiv: Pivot

The pivot indices that define the permutation matrix P.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/struct.LeastSquaresOutput.html b/lax/struct.LeastSquaresOutput.html new file mode 100644 index 00000000..70fcf9fc --- /dev/null +++ b/lax/struct.LeastSquaresOutput.html @@ -0,0 +1,43 @@ +LeastSquaresOutput in lax - Rust + + + + + + +
pub struct LeastSquaresOutput<A: Scalar> {
+    pub singular_values: Vec<A::Real>,
+    pub rank: i32,
+}
Expand description

Result of LeastSquares

+

Fields

singular_values: Vec<A::Real>

singular values

+
rank: i32

The rank of the input matrix A

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/struct.SVDOutput.html b/lax/struct.SVDOutput.html new file mode 100644 index 00000000..3f9d4e7e --- /dev/null +++ b/lax/struct.SVDOutput.html @@ -0,0 +1,45 @@ +SVDOutput in lax - Rust + + + + + + +
+

Struct lax::SVDOutput

source · []
pub struct SVDOutput<A: Scalar> {
+    pub s: Vec<A::Real>,
+    pub u: Option<Vec<A>>,
+    pub vt: Option<Vec<A>>,
+}
Expand description

Result of SVD

+

Fields

s: Vec<A::Real>

diagonal values

+
u: Option<Vec<A>>

Unitary matrix for destination space

+
vt: Option<Vec<A>>

Unitary matrix for departure space

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/struct.Tridiagonal.html b/lax/struct.Tridiagonal.html new file mode 100644 index 00000000..b2a8e5b9 --- /dev/null +++ b/lax/struct.Tridiagonal.html @@ -0,0 +1,65 @@ +Tridiagonal in lax - Rust + + + + + + +
pub struct Tridiagonal<A: Scalar> {
+    pub l: MatrixLayout,
+    pub dl: Vec<A>,
+    pub d: Vec<A>,
+    pub du: Vec<A>,
+}
Expand description

Represents a tridiagonal matrix as 3 one-dimensional vectors.

+
[d0, u1,  0,   ...,       0,
+ l1, d1, u2,            ...,
+  0, l2, d2,
+ ...           ...,  u{n-1},
+  0,  ...,  l{n-1},  d{n-1},]

Fields

l: MatrixLayout

layout of raw matrix

+
dl: Vec<A>

(n-1) sub-diagonal elements of matrix.

+
d: Vec<A>

(n) diagonal elements of matrix.

+
du: Vec<A>

(n-1) super-diagonal elements of matrix.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

The returned type after indexing.

+

Performs the indexing (container[index]) operation. Read more

+

The returned type after indexing.

+

Performs the indexing (container[index]) operation. Read more

+

Performs the mutable indexing (container[index]) operation. Read more

+

Performs the mutable indexing (container[index]) operation. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/lax/svd/struct.SVDOutput.html b/lax/svd/struct.SVDOutput.html new file mode 100644 index 00000000..cb1caa56 --- /dev/null +++ b/lax/svd/struct.SVDOutput.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/struct.SVDOutput.html...

+ + + \ No newline at end of file diff --git a/lax/svd/trait.SVD_.html b/lax/svd/trait.SVD_.html new file mode 100644 index 00000000..101973b1 --- /dev/null +++ b/lax/svd/trait.SVD_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.SVD_.html...

+ + + \ No newline at end of file diff --git a/lax/svddc/enum.UVTFlag.html b/lax/svddc/enum.UVTFlag.html new file mode 100644 index 00000000..229e6aaa --- /dev/null +++ b/lax/svddc/enum.UVTFlag.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/enum.UVTFlag.html...

+ + + \ No newline at end of file diff --git a/lax/svddc/trait.SVDDC_.html b/lax/svddc/trait.SVDDC_.html new file mode 100644 index 00000000..6dbf7fdd --- /dev/null +++ b/lax/svddc/trait.SVDDC_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.SVDDC_.html...

+ + + \ No newline at end of file diff --git a/lax/trait.Cholesky_.html b/lax/trait.Cholesky_.html new file mode 100644 index 00000000..ba1fbb2d --- /dev/null +++ b/lax/trait.Cholesky_.html @@ -0,0 +1,35 @@ +Cholesky_ in lax - Rust + + + + + + +
pub trait Cholesky_: Sized {
+    fn cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()>;
+    fn inv_cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()>;
+    fn solve_cholesky(
        l: MatrixLayout,
        uplo: UPLO,
        a: &[Self],
        b: &mut [Self]
    ) -> Result<()>; +}

Required Methods

Cholesky: wrapper of *potrf

+

Warning: Only the portion of a corresponding to UPLO is written.

+

Wrapper of *potri

+

Warning: Only the portion of a corresponding to UPLO is written.

+

Wrapper of *potrs

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.Eig_.html b/lax/trait.Eig_.html new file mode 100644 index 00000000..43e64055 --- /dev/null +++ b/lax/trait.Eig_.html @@ -0,0 +1,30 @@ +Eig_ in lax - Rust + + + + + + +
+

Trait lax::Eig_

source · []
pub trait Eig_: Scalar {
+    fn eig(
        calc_v: bool,
        l: MatrixLayout,
        a: &mut [Self]
    ) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)>; +}
Expand description

Wraps *geev for general matrices

+

Required Methods

Calculate Right eigenvalue

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.Eigh_.html b/lax/trait.Eigh_.html new file mode 100644 index 00000000..4a2b9cd0 --- /dev/null +++ b/lax/trait.Eigh_.html @@ -0,0 +1,31 @@ +Eigh_ in lax - Rust + + + + + + +
+

Trait lax::Eigh_

source · []
pub trait Eigh_: Scalar {
+    fn eigh(
        calc_eigenvec: bool,
        layout: MatrixLayout,
        uplo: UPLO,
        a: &mut [Self]
    ) -> Result<Vec<Self::Real>>; + fn eigh_generalized(
        calc_eigenvec: bool,
        layout: MatrixLayout,
        uplo: UPLO,
        a: &mut [Self],
        b: &mut [Self]
    ) -> Result<Vec<Self::Real>>; +}

Required Methods

Wraps *syev for real and *heev for complex

+

Wraps *sygv for real and *hegv for complex

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.Lapack.html b/lax/trait.Lapack.html new file mode 100644 index 00000000..9307bd28 --- /dev/null +++ b/lax/trait.Lapack.html @@ -0,0 +1,27 @@ +Lapack in lax - Rust + + + + + + +
+

Trait lax::Lapack

source · []
Expand description

Trait for primitive types which implements LAPACK subroutines

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.LeastSquaresSvdDivideConquer_.html b/lax/trait.LeastSquaresSvdDivideConquer_.html new file mode 100644 index 00000000..3a3851c1 --- /dev/null +++ b/lax/trait.LeastSquaresSvdDivideConquer_.html @@ -0,0 +1,30 @@ +LeastSquaresSvdDivideConquer_ in lax - Rust + + + + + + +
pub trait LeastSquaresSvdDivideConquer_: Scalar {
+    fn least_squares(
        a_layout: MatrixLayout,
        a: &mut [Self],
        b: &mut [Self]
    ) -> Result<LeastSquaresOutput<Self>>; + fn least_squares_nrhs(
        a_layout: MatrixLayout,
        a: &mut [Self],
        b_layout: MatrixLayout,
        b: &mut [Self]
    ) -> Result<LeastSquaresOutput<Self>>; +}
Expand description

Wraps *gelsd

+

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.OperatorNorm_.html b/lax/trait.OperatorNorm_.html new file mode 100644 index 00000000..9a6cedfc --- /dev/null +++ b/lax/trait.OperatorNorm_.html @@ -0,0 +1,28 @@ +OperatorNorm_ in lax - Rust + + + + + + +
pub trait OperatorNorm_: Scalar {
+    fn opnorm(t: NormType, l: MatrixLayout, a: &[Self]) -> Self::Real;
+}

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.QR_.html b/lax/trait.QR_.html new file mode 100644 index 00000000..8f713ff3 --- /dev/null +++ b/lax/trait.QR_.html @@ -0,0 +1,35 @@ +QR_ in lax - Rust + + + + + + +
+

Trait lax::QR_

source · []
pub trait QR_: Sized {
+    fn householder(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>>;
+    fn q(l: MatrixLayout, a: &mut [Self], tau: &[Self]) -> Result<()>;
+    fn qr(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>>;
+}

Required Methods

Execute Householder reflection as the first step of QR-decomposition

+

For C-continuous array, +this will call LQ-decomposition of the transposed matrix $ A^T = LQ^T $

+

Reconstruct Q-matrix from Householder-reflectors

+

Execute QR-decomposition at once

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.Rcond_.html b/lax/trait.Rcond_.html new file mode 100644 index 00000000..1945b38d --- /dev/null +++ b/lax/trait.Rcond_.html @@ -0,0 +1,30 @@ +Rcond_ in lax - Rust + + + + + + +
+

Trait lax::Rcond_

source · []
pub trait Rcond_: Scalar + Sized {
+    fn rcond(
        l: MatrixLayout,
        a: &[Self],
        anorm: Self::Real
    ) -> Result<Self::Real>; +}

Required Methods

Estimates the the reciprocal of the condition number of the matrix in 1-norm.

+

anorm should be the 1-norm of the matrix a.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.SVDDC_.html b/lax/trait.SVDDC_.html new file mode 100644 index 00000000..eeb46a7d --- /dev/null +++ b/lax/trait.SVDDC_.html @@ -0,0 +1,28 @@ +SVDDC_ in lax - Rust + + + + + + +
+

Trait lax::SVDDC_

source · []
pub trait SVDDC_: Scalar {
+    fn svddc(
        l: MatrixLayout,
        jobz: UVTFlag,
        a: &mut [Self]
    ) -> Result<SVDOutput<Self>>; +}

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.SVD_.html b/lax/trait.SVD_.html new file mode 100644 index 00000000..2aa8995e --- /dev/null +++ b/lax/trait.SVD_.html @@ -0,0 +1,30 @@ +SVD_ in lax - Rust + + + + + + +
+

Trait lax::SVD_

source · []
pub trait SVD_: Scalar {
+    fn svd(
        l: MatrixLayout,
        calc_u: bool,
        calc_vt: bool,
        a: &mut [Self]
    ) -> Result<SVDOutput<Self>>; +}
Expand description

Wraps *gesvd

+

Required Methods

Calculate singular value decomposition $ A = U \Sigma V^T $

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.Solve_.html b/lax/trait.Solve_.html new file mode 100644 index 00000000..63e3a252 --- /dev/null +++ b/lax/trait.Solve_.html @@ -0,0 +1,42 @@ +Solve_ in lax - Rust + + + + + + +
+

Trait lax::Solve_

source · []
pub trait Solve_: Scalar + Sized {
+    fn lu(l: MatrixLayout, a: &mut [Self]) -> Result<Pivot>;
+    fn inv(l: MatrixLayout, a: &mut [Self], p: &Pivot) -> Result<()>;
+    fn solve(
        l: MatrixLayout,
        t: Transpose,
        a: &[Self],
        p: &Pivot,
        b: &mut [Self]
    ) -> Result<()>; +}

Required Methods

Computes the LU factorization of a general m x n matrix a using +partial pivoting with row interchanges.

+

$ PA = LU $

+
Error
+
    +
  • LapackComputationalFailure { return_code } when the matrix is singular +
      +
    • Division by zero will occur if it is used to solve a system of equations +because U[(return_code-1, return_code-1)] is exactly zero.
    • +
    +
  • +
+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.Solveh_.html b/lax/trait.Solveh_.html new file mode 100644 index 00000000..500aeeb8 --- /dev/null +++ b/lax/trait.Solveh_.html @@ -0,0 +1,33 @@ +Solveh_ in lax - Rust + + + + + + +
+

Trait lax::Solveh_

source · []
pub trait Solveh_: Sized {
+    fn bk(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<Pivot>;
+    fn invh(
        l: MatrixLayout,
        uplo: UPLO,
        a: &mut [Self],
        ipiv: &Pivot
    ) -> Result<()>; + fn solveh(
        l: MatrixLayout,
        uplo: UPLO,
        a: &[Self],
        ipiv: &Pivot,
        b: &mut [Self]
    ) -> Result<()>; +}

Required Methods

Bunch-Kaufman: wrapper of *sytrf and *hetrf

+

Wrapper of *sytri and *hetri

+

Wrapper of *sytrs and *hetrs

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.Triangular_.html b/lax/trait.Triangular_.html new file mode 100644 index 00000000..2eed704f --- /dev/null +++ b/lax/trait.Triangular_.html @@ -0,0 +1,29 @@ +Triangular_ in lax - Rust + + + + + + +
pub trait Triangular_: Scalar {
+    fn solve_triangular(
        al: MatrixLayout,
        bl: MatrixLayout,
        uplo: UPLO,
        d: Diag,
        a: &[Self],
        b: &mut [Self]
    ) -> Result<()>; +}
Expand description

Wraps *trtri and *trtrs

+

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/trait.Tridiagonal_.html b/lax/trait.Tridiagonal_.html new file mode 100644 index 00000000..6f212ad8 --- /dev/null +++ b/lax/trait.Tridiagonal_.html @@ -0,0 +1,33 @@ +Tridiagonal_ in lax - Rust + + + + + + +
pub trait Tridiagonal_: Scalar + Sized {
+    fn lu_tridiagonal(
        a: Tridiagonal<Self>
    ) -> Result<LUFactorizedTridiagonal<Self>>; + fn rcond_tridiagonal(
        lu: &LUFactorizedTridiagonal<Self>
    ) -> Result<Self::Real>; + fn solve_tridiagonal(
        lu: &LUFactorizedTridiagonal<Self>,
        bl: MatrixLayout,
        t: Transpose,
        b: &mut [Self]
    ) -> Result<()>; +}
Expand description

Wraps *gttrf, *gtcon and *gttrs

+

Required Methods

Computes the LU factorization of a tridiagonal m x n matrix a using +partial pivoting with row interchanges.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/lax/triangular/enum.Diag.html b/lax/triangular/enum.Diag.html new file mode 100644 index 00000000..53a45140 --- /dev/null +++ b/lax/triangular/enum.Diag.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/enum.Diag.html...

+ + + \ No newline at end of file diff --git a/lax/triangular/trait.Triangular_.html b/lax/triangular/trait.Triangular_.html new file mode 100644 index 00000000..53af8638 --- /dev/null +++ b/lax/triangular/trait.Triangular_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.Triangular_.html...

+ + + \ No newline at end of file diff --git a/lax/tridiagonal/struct.LUFactorizedTridiagonal.html b/lax/tridiagonal/struct.LUFactorizedTridiagonal.html new file mode 100644 index 00000000..93cf6eb7 --- /dev/null +++ b/lax/tridiagonal/struct.LUFactorizedTridiagonal.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/struct.LUFactorizedTridiagonal.html...

+ + + \ No newline at end of file diff --git a/lax/tridiagonal/struct.Tridiagonal.html b/lax/tridiagonal/struct.Tridiagonal.html new file mode 100644 index 00000000..08b57a46 --- /dev/null +++ b/lax/tridiagonal/struct.Tridiagonal.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/struct.Tridiagonal.html...

+ + + \ No newline at end of file diff --git a/lax/tridiagonal/trait.Tridiagonal_.html b/lax/tridiagonal/trait.Tridiagonal_.html new file mode 100644 index 00000000..a0c2388c --- /dev/null +++ b/lax/tridiagonal/trait.Tridiagonal_.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../lax/trait.Tridiagonal_.html...

+ + + \ No newline at end of file diff --git a/lax/type.Pivot.html b/lax/type.Pivot.html new file mode 100644 index 00000000..636e58eb --- /dev/null +++ b/lax/type.Pivot.html @@ -0,0 +1,26 @@ +Pivot in lax - Rust + + + + + + +
+

Type Definition lax::Pivot

source · []
pub type Pivot = Vec<i32>;
+ \ No newline at end of file diff --git a/light.css b/light.css new file mode 100644 index 00000000..ceb83fcc --- /dev/null +++ b/light.css @@ -0,0 +1 @@ + body,#settings-menu #settings,#settings-menu #settings::before{background-color:white;color:black;}.setting-line .radio-line input{border-color:black;}.setting-line .radio-line input:checked{box-shadow:inset 0 0 0 3px white;background-color:#2196f3;}.setting-line .radio-line input:focus{box-shadow:0 0 1px 1px #2196f3;}.setting-line .radio-line input:checked:focus{box-shadow:inset 0 0 0 3px white,0 0 2px 2px #2196f3;}.setting-line .radio-line input:hover{border-color:#2196f3 !important;}.slider{background-color:#ccc;}.slider:before{background-color:white;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}h1,h2,h3,h4{color:black;}h1.fqn{border-bottom-color:#DDDDDD;}h2,h3,h4{border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre,.rustdoc.source .example-wrap{background-color:#F5F5F5;}.sidebar,.mobile-topbar,.sidebar-menu-toggle{background-color:#F5F5F5;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}.rust-logo{}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current,.sidebar a:hover{background-color:#fff;}.source .sidebar{background-color:#f1f1f1;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#FDFFD3 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5,.docblock h6{border-bottom-color:#ddd;}.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.search-results a:hover{background-color:#ddd;}.search-results a:focus{color:#000 !important;background-color:#ccc;}.search-results a:focus span{color:#000 !important;}a.result-trait:focus{background-color:#c7b6ff;}a.result-traitalias:focus{background-color:#c7b6ff;}a.result-mod:focus,a.result-externcrate:focus{background-color:#afc6e4;}a.result-enum:focus{background-color:#e7b1a0;}a.result-struct:focus{background-color:#e7b1a0;}a.result-union:focus{background-color:#e7b1a0;}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{background-color:#c6afb3;}a.result-type:focus{background-color:#e7b1a0;}a.result-associatedtype:focus{background-color:#afc6e4;}a.result-foreigntype:focus{background-color:#e7b1a0;}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{background-color:#8ce488;}a.result-constant:focus,a.result-static:focus{background-color:#afc6e4;}a.result-primitive:focus{background-color:#e7b1a0;}a.result-keyword:focus{background-color:#afc6e4;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#AD378A;}.content span.struct,.content a.struct,.block a.current.struct{color:#AD378A;}.content span.type,.content a.type,.block a.current.type{color:#AD378A;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#3873AD;}.content span.associatedtype,.content a.associatedtype,.block a.current.associatedtype{color:#3873AD;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#AD378A;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#3873AD;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#AD378A;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#3873AD;}.content span.trait,.content a.trait,.block a.current.trait{color:#6E4FC9;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#5137AD;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#AD7C37;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#3873AD;}.sidebar a{color:#356da4;}.sidebar a.current.enum{color:#a63283;}.sidebar a.current.struct{color:#a63283;}.sidebar a.current.type{color:#a63283;}.sidebar a.current.associatedtype{color:#356da4;}.sidebar a.current.foreigntype{color:#356da4;}.sidebar a.current.attr,.sidebar a.current.derive,.sidebar a.current.macro{color:#067901;}.sidebar a.current.union{color:#a63283;}.sidebar a.current.constant .sidebar a.current.static{color:#356da4;}.sidebar a.current.primitive{color:#a63283;}.sidebar a.current.externcrate .sidebar a.current.mod{color:#356da4;}.sidebar a.current.trait{color:#6849c3;}.sidebar a.current.traitalias{color:#4b349e;}.sidebar a.current.fn,.sidebar a.current.method,.sidebar a.current.tymethod{color:#a67736;}.sidebar a.current.keyword{color:#356da4;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#3873AD;}a#toggle-all-docs,a.anchor,.small-section-header a,#source-sidebar a,pre.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,.in-band a{color:#000;}.search-results a{color:initial;}a.test-arrow{color:#f5f5f5;}body.source .example-wrap pre.rust a{background:#eee;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}#crate-search,.search-input{background-color:white;border-color:#e0e0e0 !important;}.search-input:focus{border-color:#66afe9;}.module-item .stab,.import-item .stab{color:#000;}.stab.empty-impl{background:#FFF5D6;border-color:#FFC600;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.deprecated{background:#ffc4c4;border-color:#db7b7b;}.stab.portability{background:#F3DFFF;border-color:#b07bdb;}.stab.portability>code{background:none;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}#help span.bottom,#help span.top{border-color:#bfbfbf;}.rightside,.out-of-band{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgb(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label,.code-attribute{color:#999;}:target{background:#FDFFD3;border-right:3px solid #AD7C37;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#3873AD;}.tooltip::after{background-color:#000;color:#fff;}.tooltip::before{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#eee;border-color:#999;}.notable-traits-tooltiptext .notable{border-bottom-color:#DDDDDD;}#titles>button:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>button:hover,#titles>button.selected{background-color:#ffffff;border-top-color:#0089ff;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F5F5F5;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F5F5F5;border-right-color:#000;}#sidebar-filler{background-color:#F5F5F5;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow:inset 0 -1px 0 #c6cbd1;}#settings-menu>a,#help-button{border-color:#e0e0e0;background-color:#fff;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button:hover,#help-button:focus{border-color:#717171;}#settings-menu #settings,#settings-menu #settings::before{border-color:#DDDDDD;}#copy-path{color:#999;}#copy-path>img{filter:invert(50%);}#copy-path:hover>img{filter:invert(35%);}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}.search-results .result-name span.alias{color:#000;}.search-results .result-name span.grey{color:#999;}#sidebar-toggle{background-color:#F5F5F5;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F5F5F5;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.scraped-example-list .scrape-help{border-color:#555;color:#333;}.scraped-example-list .scrape-help:hover{border-color:black;color:black;}.more-examples-toggle summary,.more-examples-toggle .hide-more{color:#999;}.scraped-example .example-wrap .rust span.highlight{background:#fcffd6;}.scraped-example .example-wrap .rust span.highlight.focus{background:#f6fdb0;}.scraped-example:not(.expanded) .code-wrapper:before{background:linear-gradient(to bottom,rgba(255,255,255,1),rgba(255,255,255,0));}.scraped-example:not(.expanded) .code-wrapper:after{background:linear-gradient(to top,rgba(255,255,255,1),rgba(255,255,255,0));}.toggle-line-inner{background:#ccc;}.toggle-line:hover .toggle-line-inner{background:#999;} \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 00000000..a756f497 --- /dev/null +++ b/main.js @@ -0,0 +1,8 @@ +"use strict";if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){const l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}function getVar(name){const el=document.getElementById("rustdoc-vars");if(el){return el.attributes["data-"+name].value}else{return null}}function resourcePath(basename,extension){return getVar("root-path")+basename+getVar("resource-suffix")+extension}function hideMain(){addClass(document.getElementById(MAIN_ID),"hidden")}function showMain(){removeClass(document.getElementById(MAIN_ID),"hidden")}(function(){window.rootPath=getVar("root-path");window.currentCrate=getVar("current-crate")}());function setMobileTopbar(){const mobileLocationTitle=document.querySelector(".mobile-topbar h2.location");const locationTitle=document.querySelector(".sidebar h2.location");if(mobileLocationTitle&&locationTitle){mobileLocationTitle.innerHTML=locationTitle.innerHTML}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!=="undefined"){return ev.key}const c=ev.charCode||ev.keyCode;if(c===27){return"Escape"}return String.fromCharCode(c)}const MAIN_ID="main-content";const SETTINGS_BUTTON_ID="settings-menu";const ALTERNATIVE_DISPLAY_ID="alternative-display";const NOT_DISPLAYED_ID="not-displayed";function getSettingsButton(){return document.getElementById(SETTINGS_BUTTON_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}window.hideSettings=()=>{};function insertAfter(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)}function getOrCreateSection(id,classes){let el=document.getElementById(id);if(!el){el=document.createElement("section");el.id=id;el.className=classes;insertAfter(el,document.getElementById(MAIN_ID))}return el}function getAlternativeDisplayElem(){return getOrCreateSection(ALTERNATIVE_DISPLAY_ID,"content hidden")}function getNotDisplayedElem(){return getOrCreateSection(NOT_DISPLAYED_ID,"hidden")}function switchDisplayedElement(elemToDisplay){const el=getAlternativeDisplayElem();if(el.children.length>0){getNotDisplayedElem().appendChild(el.firstElementChild)}if(elemToDisplay===null){addClass(el,"hidden");showMain();return}el.appendChild(elemToDisplay);hideMain();removeClass(el,"hidden")}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function loadCss(cssFileName){const link=document.createElement("link");link.href=resourcePath(cssFileName,".css");link.type="text/css";link.rel="stylesheet";document.getElementsByTagName("head")[0].appendChild(link)}(function(){function loadScript(url){const script=document.createElement("script");script.src=url;document.head.append(script)}getSettingsButton().onclick=event=>{addClass(getSettingsButton(),"rotate");event.preventDefault();loadCss("settings");loadScript(resourcePath("settings",".js"))};window.searchState={loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:()=>{let el=document.getElementById("search");if(!el){el=document.createElement("section");el.id="search";getNotDisplayedElem().appendChild(el)}return el},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:()=>{if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},isDisplayed:()=>searchState.outputElement().parentElement.id===ALTERNATIVE_DISPLAY_ID,focus:()=>{searchState.input.focus()},defocus:()=>{searchState.input.blur()},showResults:search=>{if(search===null||typeof search==="undefined"){search=searchState.outputElement()}switchDisplayedElement(search);searchState.mouseMovedAfterSearch=false;document.title=searchState.title},hideResults:()=>{switchDisplayedElement(null);document.title=searchState.titleBeforeSearch;if(browserSupportsHistoryApi()){history.replaceState(null,window.currentCrate+" - Rust",getNakedUrl()+window.location.hash)}},getQueryStringParams:()=>{const params={};window.location.search.substring(1).split("&").map(s=>{const pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},setup:()=>{const search_input=searchState.input;if(!searchState.input){return}let searchLoaded=false;function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(resourcePath("search",".js"));loadScript(resourcePath("search-index",".js"))}}search_input.addEventListener("focus",()=>{search_input.origPlaceholder=search_input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});if(search_input.value!==""){loadSearch()}const params=searchState.getQueryStringParams();if(params.search!==undefined){const search=searchState.outputElement();search.innerHTML="

"+searchState.loadingText+"

";searchState.showResults(search);loadSearch()}},};function getPageId(){if(window.location.hash){const tmp=window.location.hash.replace(/^#/,"");if(tmp.length>0){return tmp}}return null}const toggleAllDocsId="toggle-all-docs";let savedHash="";function handleHashes(ev){if(ev!==null&&searchState.isDisplayed()&&ev.newURL){switchDisplayedElement(null);const hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.search+"#"+hash)}const elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}expandSection(savedHash.slice(1))}}function onHashChange(ev){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown");handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function getHelpElement(build){if(build){buildHelperPopup()}return document.getElementById("help")}function displayHelp(display,ev,help){if(display){help=help?help:getHelpElement(true);if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else{help=help?help:getHelpElement(false);if(help&&!hasClass(help,"hidden")){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}}function handleEscape(ev){searchState.clearInputTimeout();const help=getHelpElement(false);if(help&&!hasClass(help,"hidden")){displayHelp(false,ev,help)}else{switchDisplayedElement(null);if(browserSupportsHistoryApi()){history.replaceState(null,window.currentCrate+" - Rust",getNakedUrl()+window.location.hash)}ev.preventDefault()}searchState.defocus();window.hideSettings()}const disableShortcuts=getSettingValue("disable-shortcuts")==="true";function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();searchState.focus();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":displayHelp(true,ev);break;default:break}}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function addSidebarItems(){if(!window.SIDEBAR_ITEMS){return}const sidebar=document.getElementsByClassName("sidebar-elems")[0];function block(shortty,id,longty){const filtered=window.SIDEBAR_ITEMS[shortty];if(!filtered){return}const div=document.createElement("div");div.className="block "+shortty;const h3=document.createElement("h3");h3.innerHTML=`${longty}`;div.appendChild(h3);const ul=document.createElement("ul");for(const item of filtered){const name=item[0];const desc=item[1];let klass=shortty;let path;if(shortty==="mod"){path=name+"/index.html"}else{path=shortty+"."+name+".html"}const current_page=document.location.href.split("/").pop();if(path===current_page){klass+=" current"}const link=document.createElement("a");link.href=path;link.title=desc;link.className=klass;link.textContent=name;const li=document.createElement("li");li.appendChild(link);ul.appendChild(li)}div.appendChild(ul);sidebar.appendChild(div)}if(sidebar){const isModule=hasClass(document.body,"mod");if(!isModule){block("primitive","primitives","Primitive Types");block("mod","modules","Modules");block("macro","macros","Macros");block("struct","structs","Structs");block("enum","enums","Enums");block("union","unions","Unions");block("constant","constants","Constants");block("static","static","Statics");block("trait","traits","Traits");block("fn","functions","Functions");block("type","types","Type Definitions");block("foreigntype","foreign-types","Foreign Types");block("keyword","keywords","Keywords");block("traitalias","trait-aliases","Trait Aliases")}}}window.register_implementors=imp=>{const implementors=document.getElementById("implementors-list");const synthetic_implementors=document.getElementById("synthetic-implementors-list");const inlined_types=new Set();if(synthetic_implementors){onEachLazy(synthetic_implementors.getElementsByClassName("impl"),el=>{const aliases=el.getAttribute("data-aliases");if(!aliases){return}aliases.split(",").forEach(alias=>{inlined_types.add(alias)})})}let currentNbImpls=implementors.getElementsByClassName("impl").length;const traitName=document.querySelector("h1.fqn > .in-band > .trait").textContent;const baseIdName="impl-"+traitName+"-";const libs=Object.getOwnPropertyNames(imp);const ignoreExternCrates=document.querySelector("script[data-ignore-extern-crates]").getAttribute("data-ignore-extern-crates");for(const lib of libs){if(lib===window.currentCrate||ignoreExternCrates.indexOf(lib)!==-1){continue}const structs=imp[lib];struct_loop:for(const struct of structs){const list=struct.synthetic?synthetic_implementors:implementors;if(struct.synthetic){for(const struct_type of struct.types){if(inlined_types.has(struct_type)){continue struct_loop}inlined_types.add(struct_type)}}const code=document.createElement("h3");code.innerHTML=struct.text;addClass(code,"code-header");addClass(code,"in-band");onEachLazy(code.getElementsByTagName("a"),elem=>{const href=elem.getAttribute("href");if(href&&href.indexOf("http")!==0){elem.setAttribute("href",window.rootPath+href)}});const currentId=baseIdName+currentNbImpls;const anchor=document.createElement("a");anchor.href="#"+currentId;addClass(anchor,"anchor");const display=document.createElement("div");display.id=currentId;addClass(display,"impl");display.appendChild(anchor);display.appendChild(code);list.appendChild(display);currentNbImpls+=1}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function addSidebarCrates(){if(!window.ALL_CRATES){return}const sidebarElems=document.getElementsByClassName("sidebar-elems")[0];if(!sidebarElems){return}const div=document.createElement("div");div.className="block crate";div.innerHTML="

Crates

";const ul=document.createElement("ul");div.appendChild(ul);for(const crate of window.ALL_CRATES){let klass="crate";if(window.rootPath!=="./"&&crate===window.currentCrate){klass+=" current"}const link=document.createElement("a");link.href=window.rootPath+crate+"/index.html";link.className=klass;link.textContent=crate;const li=document.createElement("li");li.appendChild(link);ul.appendChild(li)}sidebarElems.appendChild(div)}function labelForToggleButton(sectionIsCollapsed){if(sectionIsCollapsed){return"+"}return"\u2212"}function toggleAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);if(!innerToggle){return}let sectionIsCollapsed=false;if(hasClass(innerToggle,"will-expand")){removeClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("rustdoc-toggle"),e=>{if(!hasClass(e,"type-contents-toggle")){e.open=true}});innerToggle.title="collapse all docs"}else{addClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("rustdoc-toggle"),e=>{if(e.parentNode.id!=="implementations-list"||(!hasClass(e,"implementors-toggle")&&!hasClass(e,"type-contents-toggle"))){e.open=false}});sectionIsCollapsed=true;innerToggle.title="expand all docs"}innerToggle.children[0].innerText=labelForToggleButton(sectionIsCollapsed)}(function(){const toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}const hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";const hideImplementations=getSettingValue("auto-hide-trait-implementations")==="true";const hideLargeItemContents=getSettingValue("auto-hide-large-items")!=="false";function setImplementorsTogglesOpen(id,open){const list=document.getElementById(id);if(list!==null){onEachLazy(list.getElementsByClassName("implementors-toggle"),e=>{e.open=open})}}if(hideImplementations){setImplementorsTogglesOpen("trait-implementations-list",false);setImplementorsTogglesOpen("blanket-implementations-list",false)}onEachLazy(document.getElementsByClassName("rustdoc-toggle"),e=>{if(!hideLargeItemContents&&hasClass(e,"type-contents-toggle")){e.open=true}if(hideMethodDocs&&hasClass(e,"method-toggle")){e.open=false}});const pageId=getPageId();if(pageId!==null){expandSection(pageId)}}());(function(){let lineNumbersFunc=()=>{};if(getSettingValue("line-numbers")==="true"){lineNumbersFunc=x=>{const count=x.textContent.split("\n").length;const elems=[];for(let i=0;i{if(hasClass(e,"compile_fail")){e.addEventListener("mouseover",function(){this.parentElement.previousElementSibling.childNodes[0].style.color="#f00"});e.addEventListener("mouseout",function(){this.parentElement.previousElementSibling.childNodes[0].style.color=""})}else if(hasClass(e,"ignore")){e.addEventListener("mouseover",function(){this.parentElement.previousElementSibling.childNodes[0].style.color="#ff9200"});e.addEventListener("mouseout",function(){this.parentElement.previousElementSibling.childNodes[0].style.color=""})}lineNumbersFunc(e)})}());function hideSidebar(){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown")}function handleClick(id,f){const elem=document.getElementById(id);if(elem){elem.addEventListener("click",f)}}handleClick("help-button",ev=>{displayHelp(true,ev)});handleClick(MAIN_ID,()=>{hideSidebar()});onEachLazy(document.getElementsByTagName("a"),el=>{if(el.hash){el.addEventListener("click",()=>{expandSection(el.hash.slice(1));hideSidebar()})}});onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"),el=>{el.addEventListener("click",e=>{if(e.target.tagName!=="SUMMARY"&&e.target.tagName!=="A"){e.preventDefault()}})});onEachLazy(document.getElementsByClassName("notable-traits"),e=>{e.onclick=function(){this.getElementsByClassName("notable-traits-tooltiptext")[0].classList.toggle("force-tooltip")}});const sidebar_menu_toggle=document.getElementsByClassName("sidebar-menu-toggle")[0];if(sidebar_menu_toggle){sidebar_menu_toggle.addEventListener("click",()=>{const sidebar=document.getElementsByClassName("sidebar")[0];if(!hasClass(sidebar,"shown")){addClass(sidebar,"shown")}else{removeClass(sidebar,"shown")}})}let buildHelperPopup=()=>{const popup=document.createElement("aside");addClass(popup,"hidden");popup.id="help";popup.addEventListener("click",ev=>{if(ev.target===popup){displayHelp(false,ev)}});const book_info=document.createElement("span");book_info.className="top";book_info.innerHTML="You can find more information in \ + the rustdoc book.";const container=document.createElement("div");const shortcuts=[["?","Show this help dialog"],["S","Focus the search field"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
"+x[0].split(" ").map((y,index)=>((index&1)===0?""+y+"":" "+y+" ")).join("")+"
"+x[1]+"
").join("");const div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";const infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ + str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;container.appendChild(book_info);container.appendChild(div_shortcuts);container.appendChild(div_infos);const rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";const rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc "+getVar("rustdoc-version");rustdoc_version.appendChild(rustdoc_version_code);container.appendChild(rustdoc_version);popup.appendChild(container);insertAfter(popup,document.querySelector("main"));buildHelperPopup=()=>{}};setMobileTopbar();addSidebarItems();addSidebarCrates();onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){let reset_button_timeout=null;window.copy_path=but=>{const parent=but.parentElement;const path=[];onEach(parent.childNodes,child=>{if(child.tagName==="A"){path.push(child.textContent)}});const el=document.createElement("textarea");el.value=path.join("::");el.setAttribute("readonly","");el.style.position="absolute";el.style.left="-9999px";document.body.appendChild(el);el.select();document.execCommand("copy");document.body.removeChild(el);but.children[0].style.display="none";let tmp;if(but.childNodes.length<2){tmp=document.createTextNode("✓");but.appendChild(tmp)}else{onEachLazy(but.childNodes,e=>{if(e.nodeType===Node.TEXT_NODE){tmp=e;return true}});tmp.textContent="✓"}if(reset_button_timeout!==null){window.clearTimeout(reset_button_timeout)}function reset_button(){tmp.textContent="";reset_button_timeout=null;but.children[0].style.display=""}reset_button_timeout=window.setTimeout(reset_button,1000)}}()) \ No newline at end of file diff --git a/ndarray-linalg/Cargo.toml b/ndarray-linalg/Cargo.toml deleted file mode 100644 index 0f0b41af..00000000 --- a/ndarray-linalg/Cargo.toml +++ /dev/null @@ -1,92 +0,0 @@ -[package] -name = "ndarray-linalg" -version = "0.18.0" -authors = ["Toshiki Teramura "] -edition = "2021" - -description = "Linear algebra package for rust-ndarray using LAPACK" -documentation = "https://docs.rs/ndarray-linalg/" -repository = "https://github.com/rust-ndarray/ndarray-linalg" -keywords = ["ndarray", "lapack", "matrix"] -license = "MIT OR Apache-2.0" -readme = "../README.md" -categories = ["algorithms", "science"] - -[features] -default = ["blas"] -blas = ["ndarray/blas"] - -netlib = ["lax/netlib"] -openblas = ["lax/openblas"] -intel-mkl = ["lax/intel-mkl-static-lp64-seq"] - -netlib-static = ["lax/netlib-static"] -netlib-system = ["lax/netlib-system"] - -openblas-static = ["lax/openblas-static"] -openblas-system = ["lax/openblas-system"] - -intel-mkl-static = ["lax/intel-mkl-static"] # deprecated, use intel-mkl-static-lp64-seq instead -intel-mkl-system = ["lax/intel-mkl-system"] # deprecated, use intel-mkl-dynamic-lp64-seq instead - -intel-mkl-dynamic-ilp64-iomp = ["lax/intel-mkl-dynamic-ilp64-iomp"] -intel-mkl-dynamic-ilp64-seq = ["lax/intel-mkl-dynamic-ilp64-seq"] -intel-mkl-dynamic-lp64-iomp = ["lax/intel-mkl-dynamic-lp64-iomp"] -intel-mkl-dynamic-lp64-seq = ["lax/intel-mkl-dynamic-lp64-seq"] -intel-mkl-static-ilp64-iomp = ["lax/intel-mkl-static-ilp64-iomp"] -intel-mkl-static-ilp64-seq = ["lax/intel-mkl-static-ilp64-seq"] -intel-mkl-static-lp64-iomp = ["lax/intel-mkl-static-lp64-iomp"] -intel-mkl-static-lp64-seq = ["lax/intel-mkl-static-lp64-seq"] - -[dependencies] -cauchy = "0.4.0" -katexit = "0.1.2" -num-complex = "0.4.0" -num-traits = "0.2.14" -rand = "0.8.3" -thiserror = "2.0.0" - -[dependencies.ndarray] -version = "0.17.1" -features = ["approx", "std"] -default-features = false - -[dependencies.lax] -version = "0.18.0" -path = "../lax" -default-features = false - -[dev-dependencies] -paste = "1.0.5" -criterion = "0.5.1" -# Keep the same version as ndarray's dependency! -approx = { version = "0.5", features = ["num-complex"] } -rand_pcg = "0.3.1" - -[[bench]] -name = "truncated_eig" -harness = false - -[[bench]] -name = "eig" -harness = false - -[[bench]] -name = "eigh" -harness = false - -[[bench]] -name = "qr" -harness = false - -[[bench]] -name = "svd" -harness = false - -[[bench]] -name = "solve" -harness = false - -[[bench]] -name = "solveh" -harness = false diff --git a/ndarray-linalg/benches/eig.rs b/ndarray-linalg/benches/eig.rs deleted file mode 100644 index 9ab124ec..00000000 --- a/ndarray-linalg/benches/eig.rs +++ /dev/null @@ -1,36 +0,0 @@ -use criterion::*; -use ndarray::*; -use ndarray_linalg::*; - -fn eig_small(c: &mut Criterion) { - let mut group = c.benchmark_group("eig"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("vecs/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let (_e, _vecs) = a.eig().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vecs/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let (_e, _vecs) = a.eig().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vals/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _result = a.eigvals().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vals/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _result = a.eigvals().unwrap(); - }) - }); - } -} - -criterion_group!(eig, eig_small); -criterion_main!(eig); diff --git a/ndarray-linalg/benches/eig_generalized.rs b/ndarray-linalg/benches/eig_generalized.rs deleted file mode 100644 index d1f5621b..00000000 --- a/ndarray-linalg/benches/eig_generalized.rs +++ /dev/null @@ -1,40 +0,0 @@ -use criterion::*; -use ndarray::*; -use ndarray_linalg::*; - -fn eig_generalized_small(c: &mut Criterion) { - let mut group = c.benchmark_group("eig"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("vecs/C/r", n), &n, |c, n| { - let a: Array2 = random((*n, *n)); - let b: Array2 = random((*n, *n)); - c.iter(|| { - let (_e, _vecs) = (a.clone(), b.clone()).eig_generalized(None).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vecs/F/r", n), &n, |c, n| { - let a: Array2 = random((*n, *n).f()); - let b: Array2 = random((*n, *n).f()); - c.iter(|| { - let (_e, _vecs) = (a.clone(), b.clone()).eig_generalized(None).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vecs/C/c", n), &n, |c, n| { - let a: Array2 = random((*n, *n)); - let b: Array2 = random((*n, *n)); - c.iter(|| { - let (_e, _vecs) = (a.clone(), b.clone()).eig_generalized(None).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vecs/F/c", n), &n, |c, n| { - let a: Array2 = random((*n, *n).f()); - let b: Array2 = random((*n, *n).f()); - c.iter(|| { - let (_e, _vecs) = (a.clone(), b.clone()).eig_generalized(None).unwrap(); - }) - }); - } -} - -criterion_group!(eig, eig_generalized_small); -criterion_main!(eig); diff --git a/ndarray-linalg/benches/eigh.rs b/ndarray-linalg/benches/eigh.rs deleted file mode 100644 index 677956d7..00000000 --- a/ndarray-linalg/benches/eigh.rs +++ /dev/null @@ -1,36 +0,0 @@ -use criterion::*; -use ndarray::*; -use ndarray_linalg::*; - -fn eigh_small(c: &mut Criterion) { - let mut group = c.benchmark_group("eigh"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("vals/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _result = a.eigvalsh(UPLO::Upper).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vals/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _result = a.eigvalsh(UPLO::Upper).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vecs/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _result = a.eigvalsh(UPLO::Upper).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vecs/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _result = a.eigvalsh(UPLO::Upper).unwrap(); - }) - }); - } -} - -criterion_group!(eigh, eigh_small); -criterion_main!(eigh); diff --git a/ndarray-linalg/benches/qr.rs b/ndarray-linalg/benches/qr.rs deleted file mode 100644 index 248be49b..00000000 --- a/ndarray-linalg/benches/qr.rs +++ /dev/null @@ -1,24 +0,0 @@ -use criterion::*; -use ndarray::*; -use ndarray_linalg::*; - -fn qr_small(c: &mut Criterion) { - let mut group = c.benchmark_group("qr"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _result = a.qr().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _result = a.qr().unwrap(); - }) - }); - } -} - -criterion_group!(qr, qr_small); -criterion_main!(qr); diff --git a/ndarray-linalg/benches/solve.rs b/ndarray-linalg/benches/solve.rs deleted file mode 100644 index 88b6e282..00000000 --- a/ndarray-linalg/benches/solve.rs +++ /dev/null @@ -1,36 +0,0 @@ -use criterion::*; -use ndarray::*; -use ndarray_linalg::*; - -fn solve_small(c: &mut Criterion) { - let mut group = c.benchmark_group("solve"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("factorize/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _lu = a.factorize().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("factorize/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _lu = a.factorize().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("inv/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _inv = a.inv().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("inv/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _inv = a.inv().unwrap(); - }) - }); - } -} - -criterion_group!(solve, solve_small); -criterion_main!(solve); diff --git a/ndarray-linalg/benches/solveh.rs b/ndarray-linalg/benches/solveh.rs deleted file mode 100644 index ee800d03..00000000 --- a/ndarray-linalg/benches/solveh.rs +++ /dev/null @@ -1,36 +0,0 @@ -use criterion::*; -use ndarray::*; -use ndarray_linalg::*; - -fn solveh_small(c: &mut Criterion) { - let mut group = c.benchmark_group("solveh"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("factorizeh/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _lu = a.factorizeh().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("factorizeh/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _lu = a.factorizeh().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("invh/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _inv = a.invh().unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("invh/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _inv = a.invh().unwrap(); - }) - }); - } -} - -criterion_group!(solveh, solveh_small); -criterion_main!(solveh); diff --git a/ndarray-linalg/benches/svd.rs b/ndarray-linalg/benches/svd.rs deleted file mode 100644 index 02ea5806..00000000 --- a/ndarray-linalg/benches/svd.rs +++ /dev/null @@ -1,102 +0,0 @@ -use criterion::*; -use ndarray::*; -use ndarray_linalg::*; - -fn svd_small(c: &mut Criterion) { - let mut group = c.benchmark_group("svd"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _ = a.svd(false, false).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _ = a.svd(false, false).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("u/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _ = a.svd(true, false).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("u/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _ = a.svd(true, false).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vt/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _ = a.svd(false, true).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("vt/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _ = a.svd(false, true).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("uvt/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _ = a.svd(false, true).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("uvt/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _ = a.svd(false, true).unwrap(); - }) - }); - } -} - -fn svddc_small(c: &mut Criterion) { - let mut group = c.benchmark_group("svddc"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _ = a.svddc(JobSvd::None).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _ = a.svddc(JobSvd::None).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("some/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _ = a.svddc(JobSvd::Some).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("some/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _ = a.svddc(JobSvd::Some).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("full/C", n), &n, |b, n| { - let a: Array2 = random((*n, *n)); - b.iter(|| { - let _ = a.svddc(JobSvd::All).unwrap(); - }) - }); - group.bench_with_input(BenchmarkId::new("full/F", n), &n, |b, n| { - let a: Array2 = random((*n, *n).f()); - b.iter(|| { - let _ = a.svddc(JobSvd::All).unwrap(); - }) - }); - } -} - -criterion_group!(svd, svd_small, svddc_small); -criterion_main!(svd); diff --git a/ndarray-linalg/benches/truncated_eig.rs b/ndarray-linalg/benches/truncated_eig.rs deleted file mode 100644 index 9fcd18b3..00000000 --- a/ndarray-linalg/benches/truncated_eig.rs +++ /dev/null @@ -1,26 +0,0 @@ -use criterion::*; -use ndarray::*; -use ndarray_linalg::*; - -fn truncated_eigh_small(c: &mut Criterion) { - let mut group = c.benchmark_group("truncated_eigh"); - for &n in &[4, 8, 16, 32, 64, 128] { - group.bench_with_input(BenchmarkId::new("C", n), &n, |b, &n| { - let a: Array2 = random((n, n)); - let a = a.t().dot(&a); - b.iter(move || { - let _result = TruncatedEig::new(a.clone(), TruncatedOrder::Largest).decompose(1); - }) - }); - group.bench_with_input(BenchmarkId::new("F", n), &n, |b, &n| { - let a: Array2 = random((n, n).f()); - let a = a.t().dot(&a); - b.iter(|| { - let _result = TruncatedEig::new(a.clone(), TruncatedOrder::Largest).decompose(1); - }) - }); - } -} - -criterion_group!(truncated_eigh, truncated_eigh_small); -criterion_main!(truncated_eigh); diff --git a/ndarray-linalg/examples/eig.rs b/ndarray-linalg/examples/eig.rs deleted file mode 100644 index 746ec2e4..00000000 --- a/ndarray-linalg/examples/eig.rs +++ /dev/null @@ -1,12 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -fn main() { - let a = arr2(&[[2.0, 1.0, 2.0], [-2.0, 2.0, 1.0], [1.0, 2.0, -2.0]]); - let (e, vecs) = a.eig().unwrap(); - println!("eigenvalues = \n{:?}", e); - println!("V = \n{:?}", vecs); - let a_c: Array2 = a.map(|f| c64::new(*f, 0.0)); - let av = a_c.dot(&vecs); - println!("AV = \n{:?}", av); -} diff --git a/ndarray-linalg/examples/eigh.rs b/ndarray-linalg/examples/eigh.rs deleted file mode 100644 index f4f36841..00000000 --- a/ndarray-linalg/examples/eigh.rs +++ /dev/null @@ -1,14 +0,0 @@ -extern crate ndarray; -extern crate ndarray_linalg; - -use ndarray::*; -use ndarray_linalg::*; - -fn main() { - let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]); - let (e, vecs) = a.eigh(UPLO::Upper).unwrap(); - println!("eigenvalues = \n{:?}", e); - println!("V = \n{:?}", vecs); - let av = a.dot(&vecs); - println!("AV = \n{:?}", av); -} diff --git a/ndarray-linalg/examples/solve.rs b/ndarray-linalg/examples/solve.rs deleted file mode 100644 index 88909c3a..00000000 --- a/ndarray-linalg/examples/solve.rs +++ /dev/null @@ -1,29 +0,0 @@ -extern crate ndarray; -extern crate ndarray_linalg; - -use ndarray::*; -use ndarray_linalg::*; - -// Solve `Ax=b` -fn solve() -> Result<(), error::LinalgError> { - let a: Array2 = random((3, 3)); - let b: Array1 = random(3); - let _x = a.solve(&b)?; - Ok(()) -} - -// Solve `Ax=b` for many b with fixed A -fn factorize() -> Result<(), error::LinalgError> { - let a: Array2 = random((3, 3)); - let f = a.factorize_into()?; // LU factorize A (A is consumed) - for _ in 0..10 { - let b: Array1 = random(3); - let _x = f.solve_into(b)?; // solve Ax=b using factorized L, U - } - Ok(()) -} - -fn main() { - solve().unwrap(); - factorize().unwrap(); -} diff --git a/ndarray-linalg/examples/solveh.rs b/ndarray-linalg/examples/solveh.rs deleted file mode 100644 index 30b2897b..00000000 --- a/ndarray-linalg/examples/solveh.rs +++ /dev/null @@ -1,32 +0,0 @@ -extern crate ndarray; -extern crate ndarray_linalg; - -use ndarray::*; -use ndarray_linalg::*; - -// Solve `Ax=b` for Hermite matrix A -fn solve() -> Result<(), error::LinalgError> { - let a: Array2 = random_hermite(3); // complex Hermite positive definite matrix - let b: Array1 = random(3); - println!("b = {:?}", &b); - let x = a.solveh(&b)?; - println!("Ax = {:?}", a.dot(&x)); - Ok(()) -} - -// Solve `Ax=b` for many b with fixed A -fn factorize() -> Result<(), error::LinalgError> { - let a: Array2 = random_hpd(3); - let f = a.factorizeh_into()?; - // once factorized, you can use it several times: - for _ in 0..10 { - let b: Array1 = random(3); - let _x = f.solveh_into(b)?; - } - Ok(()) -} - -fn main() { - solve().unwrap(); - factorize().unwrap(); -} diff --git a/ndarray-linalg/examples/tridiagonal.rs b/ndarray-linalg/examples/tridiagonal.rs deleted file mode 100644 index 676bfb28..00000000 --- a/ndarray-linalg/examples/tridiagonal.rs +++ /dev/null @@ -1,30 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -// Solve `Ax=b` for tridiagonal matrix -fn solve() -> Result<(), error::LinalgError> { - let mut a: Array2 = random((3, 3)); - let b: Array1 = random(3); - a[[0, 2]] = 0.0; - a[[2, 0]] = 0.0; - let _x = a.solve_tridiagonal(&b)?; - Ok(()) -} - -// Solve `Ax=b` for many b with fixed A -fn factorize() -> Result<(), error::LinalgError> { - let mut a: Array2 = random((3, 3)); - a[[0, 2]] = 0.0; - a[[2, 0]] = 0.0; - let f = a.factorize_tridiagonal()?; // LU factorize A (A is *not* consumed) - for _ in 0..10 { - let b: Array1 = random(3); - let _x = f.solve_tridiagonal_into(b)?; // solve Ax=b using factorized L, U - } - Ok(()) -} - -fn main() { - solve().unwrap(); - factorize().unwrap(); -} diff --git a/ndarray-linalg/examples/truncated_eig.rs b/ndarray-linalg/examples/truncated_eig.rs deleted file mode 100644 index 58172ec6..00000000 --- a/ndarray-linalg/examples/truncated_eig.rs +++ /dev/null @@ -1,23 +0,0 @@ -extern crate ndarray; -extern crate ndarray_linalg; - -use ndarray::*; -use ndarray_linalg::*; - -fn main() { - let n = 10; - let v = random_unitary(n); - - // set eigenvalues in decreasing order - let t = Array1::linspace(n as f64, -(n as f64), n); - - println!("Generate spectrum: {:?}", &t); - - let t = Array2::from_diag(&t); - let a = v.dot(&t.dot(&v.t())); - - // calculate the truncated eigenproblem decomposition - for (val, _) in TruncatedEig::new(a, TruncatedOrder::Largest) { - println!("Found eigenvalue {}", val[0]); - } -} diff --git a/ndarray-linalg/examples/truncated_svd.rs b/ndarray-linalg/examples/truncated_svd.rs deleted file mode 100644 index 1416368c..00000000 --- a/ndarray-linalg/examples/truncated_svd.rs +++ /dev/null @@ -1,24 +0,0 @@ -extern crate ndarray; -extern crate ndarray_linalg; - -use ndarray::*; -use ndarray_linalg::*; - -fn main() { - let a = arr2(&[[3., 2., 2.], [2., 3., -2.]]); - - // calculate the truncated singular value decomposition for 2 singular values - let result = TruncatedSvd::new(a, TruncatedOrder::Largest) - .decompose(2) - .unwrap(); - - // acquire singular values, left-singular vectors and right-singular vectors - let (u, sigma, v_t) = result.values_vectors(); - println!("Result of the singular value decomposition A = UΣV^T:"); - println!(" === U ==="); - println!("{:?}", u); - println!(" === Σ ==="); - println!("{:?}", Array2::from_diag(&sigma)); - println!(" === V^T ==="); - println!("{:?}", v_t); -} diff --git a/ndarray-linalg/src/assert.rs b/ndarray-linalg/src/assert.rs deleted file mode 100644 index 74c1618b..00000000 --- a/ndarray-linalg/src/assert.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! Assertions for array - -use ndarray::*; -use std::fmt::Debug; - -use super::norm::*; -use super::types::*; - -/// check two values are close in terms of the relative tolerance -pub fn rclose(test: A, truth: A, rtol: A::Real) { - let dev = (test - truth).abs() / truth.abs(); - if dev > rtol { - eprintln!("==== Assetion Failed ===="); - eprintln!("Expected = {}", truth); - eprintln!("Actual = {}", test); - panic!("Too large deviation in relative tolerance: {}", dev); - } -} - -/// check two values are close in terms of the absolute tolerance -pub fn aclose(test: A, truth: A, atol: A::Real) { - let dev = (test - truth).abs(); - if dev > atol { - eprintln!("==== Assetion Failed ===="); - eprintln!("Expected = {}", truth); - eprintln!("Actual = {}", test); - panic!("Too large deviation in absolute tolerance: {}", dev); - } -} - -/// check two arrays are close in maximum norm -pub fn close_max(test: &ArrayBase, truth: &ArrayBase, atol: A::Real) -where - A: Scalar + Lapack, - S1: Data, - S2: Data, - D: Dimension, - D::Pattern: PartialEq + Debug, -{ - assert_eq!(test.dim(), truth.dim()); - let tol = (test - truth).norm_max(); - if tol > atol { - eprintln!("==== Assetion Failed ===="); - eprintln!("Expected:\n{}", truth); - eprintln!("Actual:\n{}", test); - panic!("Too large deviation in maximum norm: {} > {}", tol, atol); - } -} - -/// check two arrays are close in L1 norm -pub fn close_l1(test: &ArrayBase, truth: &ArrayBase, rtol: A::Real) -where - A: Scalar + Lapack, - S1: Data, - S2: Data, - D: Dimension, - D::Pattern: PartialEq + Debug, -{ - assert_eq!(test.dim(), truth.dim()); - let tol = (test - truth).norm_l1() / truth.norm_l1(); - if tol > rtol { - eprintln!("==== Assetion Failed ===="); - eprintln!("Expected:\n{}", truth); - eprintln!("Actual:\n{}", test); - panic!("Too large deviation in L1-norm: {} > {}", tol, rtol); - } -} - -/// check two arrays are close in L2 norm -pub fn close_l2(test: &ArrayBase, truth: &ArrayBase, rtol: A::Real) -where - A: Scalar + Lapack, - S1: Data, - S2: Data, - D: Dimension, - D::Pattern: PartialEq + Debug, -{ - assert_eq!(test.dim(), truth.dim()); - let tol = (test - truth).norm_l2() / truth.norm_l2(); - if tol > rtol { - eprintln!("==== Assetion Failed ===="); - eprintln!("Expected:\n{}", truth); - eprintln!("Actual:\n{}", test); - panic!("Too large deviation in L2-norm: {} > {} ", tol, rtol); - } -} - -macro_rules! generate_assert { - ($assert:ident, $close:tt) => { - #[macro_export] - macro_rules! $assert { - ($test: expr,$truth: expr,$tol: expr) => { - $crate::$close($test, $truth, $tol); - }; - ($test: expr,$truth: expr,$tol: expr; $comment: expr) => { - eprintln!($comment); - $crate::$close($test, $truth, $tol); - }; - } - }; -} // generate_assert! - -generate_assert!(assert_rclose, rclose); -generate_assert!(assert_aclose, aclose); -generate_assert!(assert_close_max, close_max); -generate_assert!(assert_close_l1, close_l1); -generate_assert!(assert_close_l2, close_l2); diff --git a/ndarray-linalg/src/cholesky.rs b/ndarray-linalg/src/cholesky.rs deleted file mode 100644 index 58cc5cee..00000000 --- a/ndarray-linalg/src/cholesky.rs +++ /dev/null @@ -1,468 +0,0 @@ -//! Cholesky decomposition of Hermitian (or real symmetric) positive definite matrices -//! -//! See the [Wikipedia page about Cholesky -//! decomposition](https://en.wikipedia.org/wiki/Cholesky_decomposition) for -//! more information. -//! -//! # Example -//! -//! Using the Cholesky decomposition of `A` for various operations, where `A` -//! is a Hermitian (or real symmetric) positive definite matrix: -//! -//! ``` -//! #[macro_use] -//! extern crate ndarray; -//! extern crate ndarray_linalg; -//! -//! use ndarray::prelude::*; -//! use ndarray_linalg::cholesky::*; -//! # fn main() { -//! -//! let a: Array2 = array![ -//! [ 4., 12., -16.], -//! [ 12., 37., -43.], -//! [-16., -43., 98.] -//! ]; -//! -//! // Obtain `L` -//! let lower = a.cholesky(UPLO::Lower).unwrap(); -//! assert!(lower.abs_diff_eq(&array![ -//! [ 2., 0., 0.], -//! [ 6., 1., 0.], -//! [-8., 5., 3.] -//! ], 1e-9)); -//! -//! // Find the determinant of `A` -//! let det = a.detc().unwrap(); -//! assert!((det - 36.).abs() < 1e-9); -//! -//! // Solve `A * x = b` -//! let b = array![4., 13., -11.]; -//! let x = a.solvec(&b).unwrap(); -//! assert!(x.abs_diff_eq(&array![-2., 1., 0.], 1e-9)); -//! # } -//! ``` - -use ndarray::*; -use num_traits::Float; - -use crate::convert::*; -use crate::error::*; -use crate::layout::*; -use crate::triangular::IntoTriangular; -use crate::types::*; - -pub use lax::UPLO; - -/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix -pub struct CholeskyFactorized { - /// `L` from the decomposition `A = L * L^H` or `U` from the decomposition - /// `A = U^H * U`. - pub factor: ArrayBase, - /// If this is `UPLO::Lower`, then `self.factor` is `L`. If this is - /// `UPLO::Upper`, then `self.factor` is `U`. - pub uplo: UPLO, -} - -impl CholeskyFactorized -where - A: Scalar + Lapack, - S: DataMut, -{ - /// Returns `L` from the Cholesky decomposition `A = L * L^H`. - /// - /// If `self.uplo == UPLO::Lower`, then no computations need to be - /// performed; otherwise, the conjugate transpose of `self.factor` is - /// calculated. - pub fn into_lower(self) -> ArrayBase { - match self.uplo { - UPLO::Lower => self.factor, - UPLO::Upper => self.factor.reversed_axes().mapv_into(|elem| elem.conj()), - } - } - - /// Returns `U` from the Cholesky decomposition `A = U^H * U`. - /// - /// If `self.uplo == UPLO::Upper`, then no computations need to be - /// performed; otherwise, the conjugate transpose of `self.factor` is - /// calculated. - pub fn into_upper(self) -> ArrayBase { - match self.uplo { - UPLO::Lower => self.factor.reversed_axes().mapv_into(|elem| elem.conj()), - UPLO::Upper => self.factor, - } - } -} - -impl DeterminantC for CholeskyFactorized -where - A: Scalar + Lapack, - S: Data, -{ - type Output = ::Real; - - fn detc(&self) -> Self::Output { - Float::exp(self.ln_detc()) - } - - fn ln_detc(&self) -> Self::Output { - self.factor - .diag() - .iter() - .map(|elem| Float::ln(elem.square())) - .sum::() - } -} - -impl DeterminantCInto for CholeskyFactorized -where - A: Scalar + Lapack, - S: Data, -{ - type Output = ::Real; - - fn detc_into(self) -> Self::Output { - self.detc() - } - - fn ln_detc_into(self) -> Self::Output { - self.ln_detc() - } -} - -impl InverseC for CholeskyFactorized -where - A: Scalar + Lapack, - S: Data, -{ - type Output = Array2; - - fn invc(&self) -> Result { - let f = CholeskyFactorized { - factor: replicate(&self.factor), - uplo: self.uplo, - }; - f.invc_into() - } -} - -impl InverseCInto for CholeskyFactorized -where - A: Scalar + Lapack, - S: DataMut, -{ - type Output = ArrayBase; - - fn invc_into(self) -> Result { - let mut a = self.factor; - A::inv_cholesky(a.square_layout()?, self.uplo, a.as_allocated_mut()?)?; - triangular_fill_hermitian(&mut a, self.uplo); - Ok(a) - } -} - -impl SolveC for CholeskyFactorized -where - A: Scalar + Lapack, - S: Data, -{ - fn solvec_inplace<'a, Sb>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - A::solve_cholesky( - self.factor.square_layout()?, - self.uplo, - self.factor.as_allocated()?, - b.as_slice_mut().unwrap(), - )?; - Ok(b) - } -} - -/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference -pub trait Cholesky { - type Output; - - /// Computes the Cholesky decomposition of the Hermitian (or real - /// symmetric) positive definite matrix. - /// - /// If the argument is `UPLO::Upper`, then computes the decomposition `A = - /// U^H * U` using the upper triangular portion of `A` and returns `U`. - /// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition - /// `A = L * L^H` using the lower triangular portion of `A` and returns - /// `L`. - fn cholesky(&self, uplo: UPLO) -> Result; -} - -/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix -pub trait CholeskyInto { - type Output; - /// Computes the Cholesky decomposition of the Hermitian (or real - /// symmetric) positive definite matrix. - /// - /// If the argument is `UPLO::Upper`, then computes the decomposition `A = - /// U^H * U` using the upper triangular portion of `A` and returns `U`. - /// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition - /// `A = L * L^H` using the lower triangular portion of `A` and returns - /// `L`. - fn cholesky_into(self, uplo: UPLO) -> Result; -} - -/// Cholesky decomposition of Hermitian (or real symmetric) positive definite mutable reference of matrix -pub trait CholeskyInplace { - /// Computes the Cholesky decomposition of the Hermitian (or real - /// symmetric) positive definite matrix, writing the result (`L` or `U` - /// according to the argument) to `self` and returning it. - /// - /// If the argument is `UPLO::Upper`, then computes the decomposition `A = - /// U^H * U` using the upper triangular portion of `A` and writes `U`. - /// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition - /// `A = L * L^H` using the lower triangular portion of `A` and writes `L`. - fn cholesky_inplace(&mut self, uplo: UPLO) -> Result<&mut Self>; -} - -impl Cholesky for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type Output = Array2; - - fn cholesky(&self, uplo: UPLO) -> Result> { - let a = replicate(self); - a.cholesky_into(uplo) - } -} - -impl CholeskyInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type Output = Self; - - fn cholesky_into(mut self, uplo: UPLO) -> Result { - self.cholesky_inplace(uplo)?; - Ok(self) - } -} - -impl CholeskyInplace for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - fn cholesky_inplace(&mut self, uplo: UPLO) -> Result<&mut Self> { - A::cholesky(self.square_layout()?, uplo, self.as_allocated_mut()?)?; - Ok(self.into_triangular(uplo)) - } -} - -/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference -pub trait FactorizeC { - /// Computes the Cholesky decomposition of the Hermitian (or real - /// symmetric) positive definite matrix. - /// - /// If the argument is `UPLO::Upper`, then computes the decomposition `A = - /// U^H * U` using the upper triangular portion of `A` and returns the - /// factorization containing `U`. Otherwise, if the argument is - /// `UPLO::Lower`, computes the decomposition `A = L * L^H` using the lower - /// triangular portion of `A` and returns the factorization containing `L`. - fn factorizec(&self, uplo: UPLO) -> Result>; -} - -/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix -pub trait FactorizeCInto { - /// Computes the Cholesky decomposition of the Hermitian (or real - /// symmetric) positive definite matrix. - /// - /// If the argument is `UPLO::Upper`, then computes the decomposition `A = - /// U^H * U` using the upper triangular portion of `A` and returns the - /// factorization containing `U`. Otherwise, if the argument is - /// `UPLO::Lower`, computes the decomposition `A = L * L^H` using the lower - /// triangular portion of `A` and returns the factorization containing `L`. - fn factorizec_into(self, uplo: UPLO) -> Result>; -} - -impl FactorizeCInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - fn factorizec_into(self, uplo: UPLO) -> Result> { - Ok(CholeskyFactorized { - factor: self.cholesky_into(uplo)?, - uplo, - }) - } -} - -impl FactorizeC> for ArrayBase -where - A: Scalar + Lapack, - Si: Data, -{ - fn factorizec(&self, uplo: UPLO) -> Result>> { - Ok(CholeskyFactorized { - factor: self.cholesky(uplo)?, - uplo, - }) - } -} - -/// Solve systems of linear equations with Hermitian (or real symmetric) -/// positive definite coefficient matrices -pub trait SolveC { - /// Solves a system of linear equations `A * x = b` with Hermitian (or real - /// symmetric) positive definite matrix `A`, where `A` is `self`, `b` is - /// the argument, and `x` is the successful result. - fn solvec>(&self, b: &ArrayBase) -> Result> { - let mut b = replicate(b); - self.solvec_inplace(&mut b)?; - Ok(b) - } - /// Solves a system of linear equations `A * x = b` with Hermitian (or real - /// symmetric) positive definite matrix `A`, where `A` is `self`, `b` is - /// the argument, and `x` is the successful result. - fn solvec_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solvec_inplace(&mut b)?; - Ok(b) - } - /// Solves a system of linear equations `A * x = b` with Hermitian (or real - /// symmetric) positive definite matrix `A`, where `A` is `self`, `b` is - /// the argument, and `x` is the successful result. The value of `x` is - /// also assigned to the argument. - fn solvec_inplace<'a, S: DataMut>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; -} - -impl SolveC for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn solvec_inplace<'a, Sb>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - self.factorizec(UPLO::Upper)?.solvec_inplace(b) - } -} - -/// Inverse of Hermitian (or real symmetric) positive definite matrix ref -pub trait InverseC { - type Output; - /// Computes the inverse of the Hermitian (or real symmetric) positive - /// definite matrix. - fn invc(&self) -> Result; -} - -/// Inverse of Hermitian (or real symmetric) positive definite matrix -pub trait InverseCInto { - type Output; - /// Computes the inverse of the Hermitian (or real symmetric) positive - /// definite matrix. - fn invc_into(self) -> Result; -} - -impl InverseC for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type Output = Array2; - - fn invc(&self) -> Result { - self.factorizec(UPLO::Upper)?.invc_into() - } -} - -impl InverseCInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type Output = Self; - - fn invc_into(self) -> Result { - self.factorizec_into(UPLO::Upper)?.invc_into() - } -} - -/// Determinant of Hermitian (or real symmetric) positive definite matrix ref -pub trait DeterminantC { - type Output; - - /// Computes the determinant of the Hermitian (or real symmetric) positive - /// definite matrix. - fn detc(&self) -> Self::Output; - - /// Computes the natural log of the determinant of the Hermitian (or real - /// symmetric) positive definite matrix. - /// - /// This method is more robust than `.detc()` to very small or very large - /// determinants since it returns the natural logarithm of the determinant - /// rather than the determinant itself. - fn ln_detc(&self) -> Self::Output; -} - -/// Determinant of Hermitian (or real symmetric) positive definite matrix -pub trait DeterminantCInto { - type Output; - - /// Computes the determinant of the Hermitian (or real symmetric) positive - /// definite matrix. - fn detc_into(self) -> Self::Output; - - /// Computes the natural log of the determinant of the Hermitian (or real - /// symmetric) positive definite matrix. - /// - /// This method is more robust than `.detc_into()` to very small or very - /// large determinants since it returns the natural logarithm of the - /// determinant rather than the determinant itself. - fn ln_detc_into(self) -> Self::Output; -} - -impl DeterminantC for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type Output = Result<::Real>; - - fn detc(&self) -> Self::Output { - Ok(Float::exp(self.ln_detc()?)) - } - - fn ln_detc(&self) -> Self::Output { - Ok(self.factorizec(UPLO::Upper)?.ln_detc()) - } -} - -impl DeterminantCInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type Output = Result<::Real>; - - fn detc_into(self) -> Self::Output { - Ok(Float::exp(self.ln_detc_into()?)) - } - - fn ln_detc_into(self) -> Self::Output { - Ok(self.factorizec_into(UPLO::Upper)?.ln_detc_into()) - } -} diff --git a/ndarray-linalg/src/convert.rs b/ndarray-linalg/src/convert.rs deleted file mode 100644 index c808211e..00000000 --- a/ndarray-linalg/src/convert.rs +++ /dev/null @@ -1,144 +0,0 @@ -//! utilities for convert array - -use lax::UPLO; -use ndarray::*; - -use super::error::*; -use super::layout::*; -use super::types::*; - -pub fn into_col(a: ArrayBase) -> ArrayBase -where - S: Data, -{ - let n = a.len(); - a.into_shape_with_order((n, 1)).unwrap() -} - -pub fn into_row(a: ArrayBase) -> ArrayBase -where - S: Data, -{ - let n = a.len(); - a.into_shape_with_order((1, n)).unwrap() -} - -pub fn flatten(a: ArrayBase) -> ArrayBase -where - S: Data, -{ - let n = a.len(); - a.into_shape_with_order(n).unwrap() -} - -pub fn into_matrix(l: MatrixLayout, a: Vec) -> Result> -where - S: DataOwned, -{ - match l { - MatrixLayout::C { row, lda } => { - Ok(ArrayBase::from_shape_vec((row as usize, lda as usize), a)?) - } - MatrixLayout::F { col, lda } => Ok(ArrayBase::from_shape_vec( - (lda as usize, col as usize).f(), - a, - )?), - } -} - -pub fn replicate(a: &ArrayBase) -> ArrayBase -where - A: Copy, - Sv: Data, - So: DataOwned + DataMut, - D: Dimension, -{ - unsafe { - let ret = ArrayBase::::build_uninit(a.dim(), |view| { - a.assign_to(view); - }); - ret.assume_init() - } -} - -fn clone_with_layout(l: MatrixLayout, a: &ArrayBase) -> ArrayBase -where - A: Copy, - Si: Data, - So: DataOwned + DataMut, -{ - let shape_builder = match l { - MatrixLayout::C { row, lda } => (row as usize, lda as usize).set_f(false), - MatrixLayout::F { col, lda } => (lda as usize, col as usize).set_f(true), - }; - unsafe { - let ret = ArrayBase::::build_uninit(shape_builder, |view| { - a.assign_to(view); - }); - ret.assume_init() - } -} - -pub fn transpose_data(a: &mut ArrayBase) -> Result<&mut ArrayBase> -where - A: Copy, - S: DataOwned + DataMut, -{ - let l = a.layout()?.toggle_order(); - let new = clone_with_layout(l, a); - *a = new; - Ok(a) -} - -pub fn generalize(a: Array) -> ArrayBase -where - S: DataOwned, - D: Dimension, -{ - // FIXME - // https://github.com/bluss/rust-ndarray/issues/325 - let strides: Vec = a.strides().to_vec(); - let new = if a.is_standard_layout() { - ArrayBase::from_shape_vec(a.dim(), a.into_raw_vec_and_offset().0).unwrap() - } else { - ArrayBase::from_shape_vec(a.dim().f(), a.into_raw_vec_and_offset().0).unwrap() - }; - assert_eq!( - new.strides(), - strides.as_slice(), - "Custom stride is not supported" - ); - new -} - -/// Fills in the remainder of a Hermitian matrix that's represented by only one -/// triangle. -/// -/// LAPACK methods on Hermitian matrices usually read/write only one triangular -/// portion of the matrix. This function fills in the other half based on the -/// data in the triangular portion corresponding to `uplo`. -/// -/// ***Panics*** if `a` is not square. -pub(crate) fn triangular_fill_hermitian(a: &mut ArrayBase, uplo: UPLO) -where - A: Scalar + Lapack, - S: DataMut, -{ - assert!(a.is_square()); - match uplo { - UPLO::Upper => { - for row in 0..a.nrows() { - for col in 0..row { - a[(row, col)] = a[(col, row)].conj(); - } - } - } - UPLO::Lower => { - for col in 0..a.ncols() { - for row in 0..col { - a[(row, col)] = a[(col, row)].conj(); - } - } - } - } -} diff --git a/ndarray-linalg/src/diagonal.rs b/ndarray-linalg/src/diagonal.rs deleted file mode 100644 index a7adad4a..00000000 --- a/ndarray-linalg/src/diagonal.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! Vector as a Diagonal matrix - -use ndarray::*; - -use super::operator::*; -use super::types::*; - -/// Vector as a Diagonal matrix -pub struct Diagonal { - diag: ArrayBase, -} - -pub trait IntoDiagonal { - fn into_diagonal(self) -> Diagonal; -} - -pub trait AsDiagonal { - fn as_diagonal(&self) -> Diagonal>; -} - -impl IntoDiagonal for ArrayBase { - fn into_diagonal(self) -> Diagonal { - Diagonal { diag: self } - } -} - -impl> AsDiagonal for ArrayBase { - fn as_diagonal(&self) -> Diagonal> { - Diagonal { diag: self.view() } - } -} - -impl LinearOperator for Diagonal -where - A: Scalar, - Sa: Data, -{ - type Elem = A; - - fn apply_mut(&self, a: &mut ArrayBase) - where - S: DataMut, - { - for (val, d) in a.iter_mut().zip(self.diag.iter()) { - *val *= *d; - } - } -} diff --git a/ndarray-linalg/src/eig.rs b/ndarray-linalg/src/eig.rs deleted file mode 100644 index 03e3ee03..00000000 --- a/ndarray-linalg/src/eig.rs +++ /dev/null @@ -1,163 +0,0 @@ -//! Eigenvalue decomposition for non-symmetric square matrices - -use crate::error::*; -use crate::layout::*; -use crate::types::*; -pub use lax::GeneralizedEigenvalue; -use ndarray::*; - -#[cfg_attr(doc, katexit::katexit)] -/// Eigenvalue decomposition of general matrix reference -pub trait Eig { - /// EigVec is the right eivenvector - type EigVal; - type EigVec; - /// Calculate eigenvalues with the right eigenvector - /// - /// $$ A u_i = \lambda_i u_i $$ - /// - /// ``` - /// use ndarray::*; - /// use ndarray_linalg::*; - /// - /// let a: Array2 = array![ - /// [-1.01, 0.86, -4.60, 3.31, -4.81], - /// [ 3.98, 0.53, -7.04, 5.29, 3.55], - /// [ 3.30, 8.26, -3.89, 8.20, -1.51], - /// [ 4.43, 4.96, -7.66, -7.33, 6.18], - /// [ 7.31, -6.43, -6.16, 2.47, 5.58], - /// ]; - /// let (eigs, vecs) = a.eig().unwrap(); - /// - /// let a = a.map(|v| v.as_c()); - /// for (&e, vec) in eigs.iter().zip(vecs.axis_iter(Axis(1))) { - /// let ev = vec.map(|v| v * e); - /// let av = a.dot(&vec); - /// assert_close_l2!(&av, &ev, 1e-5); - /// } - /// ``` - fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>; -} - -impl Eig for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type EigVal = Array1; - type EigVec = Array2; - - fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)> { - let mut a = self.to_owned(); - let layout = a.square_layout()?; - let (s, t) = A::eig(true, layout, a.as_allocated_mut()?)?; - let n = layout.len() as usize; - Ok(( - ArrayBase::from(s), - Array2::from_shape_vec((n, n).f(), t).unwrap(), - )) - } -} - -/// Calculate eigenvalues without eigenvectors -pub trait EigVals { - type EigVal; - fn eigvals(&self) -> Result; -} - -impl EigVals for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type EigVal = Array1; - - fn eigvals(&self) -> Result { - let mut a = self.to_owned(); - let (s, _) = A::eig(false, a.square_layout()?, a.as_allocated_mut()?)?; - Ok(ArrayBase::from(s)) - } -} - -#[cfg_attr(doc, katexit::katexit)] -/// Eigenvalue decomposition of general matrix reference -pub trait EigGeneralized { - /// EigVec is the right eivenvector - type EigVal; - type EigVec; - type Real; - /// Calculate eigenvalues with the right eigenvector - /// - /// $$ A u_i = \lambda_i B u_i $$ - /// - /// ``` - /// use ndarray::*; - /// use ndarray_linalg::*; - /// - /// let a: Array2 = array![ - /// [-1.01, 0.86, -4.60, 3.31, -4.81], - /// [ 3.98, 0.53, -7.04, 5.29, 3.55], - /// [ 3.30, 8.26, -3.89, 8.20, -1.51], - /// [ 4.43, 4.96, -7.66, -7.33, 6.18], - /// [ 7.31, -6.43, -6.16, 2.47, 5.58], - /// ]; - /// let b: Array2 = array![ - /// [ 1.23, -4.56, 7.89, 0.12, -3.45], - /// [ 6.78, -9.01, 2.34, -5.67, 8.90], - /// [-1.11, 3.33, -6.66, 9.99, -2.22], - /// [ 4.44, -7.77, 0.00, 1.11, 5.55], - /// [-8.88, 6.66, -3.33, 2.22, -9.99], - /// ]; - /// let (geneigs, vecs) = (a.clone(), b.clone()).eig_generalized(None).unwrap(); - /// - /// let a = a.map(|v| v.as_c()); - /// let b = b.map(|v| v.as_c()); - /// for (ge, vec) in geneigs.iter().zip(vecs.axis_iter(Axis(1))) { - /// if let GeneralizedEigenvalue::Finite(e, _) = ge { - /// let ebv = b.dot(&vec).map(|v| v * e); - /// let av = a.dot(&vec); - /// assert_close_l2!(&av, &ebv, 1e-5); - /// } - /// } - /// ``` - /// - /// # Arguments - /// - /// * `thresh_opt` - An optional threshold for determining approximate zero |β| values when - /// computing the eigenvalues as α/β. If `None`, no approximate comparisons to zero will be - /// made. - fn eig_generalized( - &self, - thresh_opt: Option, - ) -> Result<(Self::EigVal, Self::EigVec)>; -} - -impl EigGeneralized for (ArrayBase, ArrayBase) -where - A: Scalar + Lapack, - S: Data, -{ - type EigVal = Array1>; - type EigVec = Array2; - type Real = A::Real; - - fn eig_generalized( - &self, - thresh_opt: Option, - ) -> Result<(Self::EigVal, Self::EigVec)> { - let (mut a, mut b) = (self.0.to_owned(), self.1.to_owned()); - let layout = a.square_layout()?; - let (s, t) = A::eig_generalized( - true, - layout, - a.as_allocated_mut()?, - b.as_allocated_mut()?, - thresh_opt, - )?; - let n = layout.len() as usize; - Ok(( - ArrayBase::from(s), - Array2::from_shape_vec((n, n).f(), t).unwrap(), - )) - } -} diff --git a/ndarray-linalg/src/eigh.rs b/ndarray-linalg/src/eigh.rs deleted file mode 100644 index 837f51f8..00000000 --- a/ndarray-linalg/src/eigh.rs +++ /dev/null @@ -1,277 +0,0 @@ -//! Eigendecomposition for Hermitian matrices. -//! -//! For a Hermitian matrix `A`, this solves the eigenvalue problem `A V = V D` -//! for `D` and `V`, where `D` is the diagonal matrix of eigenvalues in -//! ascending order and `V` is the orthonormal matrix of corresponding -//! eigenvectors. -//! -//! For a pair of Hermitian matrices `A` and `B` where `B` is also positive -//! definite, this solves the generalized eigenvalue problem `A V = B V D`, -//! where `D` is the diagonal matrix of generalized eigenvalues in ascending -//! order and `V` is the matrix of corresponding generalized eigenvectors. The -//! matrix `V` is normalized such that `V^H B V = I`. -//! -//! # Example -//! -//! Find the eigendecomposition of a Hermitian (or real symmetric) matrix. -//! -//! ``` -//! use approx::assert_abs_diff_eq; -//! use ndarray::{array, Array2}; -//! use ndarray_linalg::{Eigh, UPLO}; -//! -//! let a: Array2 = array![ -//! [2., 1.], -//! [1., 2.], -//! ]; -//! let (eigvals, eigvecs) = a.eigh(UPLO::Lower)?; -//! assert_abs_diff_eq!(eigvals, array![1., 3.]); -//! assert_abs_diff_eq!( -//! a.dot(&eigvecs), -//! eigvecs.dot(&Array2::from_diag(&eigvals)), -//! ); -//! # Ok::<(), Box>(()) -//! ``` - -use ndarray::*; - -use crate::diagonal::*; -use crate::error::*; -use crate::layout::*; -use crate::operator::LinearOperator; -use crate::types::*; -use crate::UPLO; - -/// Eigenvalue decomposition of Hermite matrix reference -pub trait Eigh { - type EigVal; - type EigVec; - fn eigh(&self, uplo: UPLO) -> Result<(Self::EigVal, Self::EigVec)>; -} - -/// Eigenvalue decomposition of mutable reference of Hermite matrix -pub trait EighInplace { - type EigVal; - fn eigh_inplace(&mut self, uplo: UPLO) -> Result<(Self::EigVal, &mut Self)>; -} - -/// Eigenvalue decomposition of Hermite matrix -pub trait EighInto: Sized { - type EigVal; - fn eigh_into(self, uplo: UPLO) -> Result<(Self::EigVal, Self)>; -} - -impl EighInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type EigVal = Array1; - - fn eigh_into(mut self, uplo: UPLO) -> Result<(Self::EigVal, Self)> { - let (val, _) = self.eigh_inplace(uplo)?; - Ok((val, self)) - } -} - -impl EighInto for (ArrayBase, ArrayBase) -where - A: Scalar + Lapack, - S: DataMut, - S2: DataMut, -{ - type EigVal = Array1; - - fn eigh_into(mut self, uplo: UPLO) -> Result<(Self::EigVal, Self)> { - let (val, _) = self.eigh_inplace(uplo)?; - Ok((val, self)) - } -} - -impl Eigh for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type EigVal = Array1; - type EigVec = Array2; - - fn eigh(&self, uplo: UPLO) -> Result<(Self::EigVal, Self::EigVec)> { - let a = self.to_owned(); - a.eigh_into(uplo) - } -} - -impl Eigh for (ArrayBase, ArrayBase) -where - A: Scalar + Lapack, - S: Data, - S2: Data, -{ - type EigVal = Array1; - type EigVec = (Array2, Array2); - - fn eigh(&self, uplo: UPLO) -> Result<(Self::EigVal, Self::EigVec)> { - let (a, b) = (self.0.to_owned(), self.1.to_owned()); - (a, b).eigh_into(uplo) - } -} - -impl EighInplace for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type EigVal = Array1; - - fn eigh_inplace(&mut self, uplo: UPLO) -> Result<(Self::EigVal, &mut Self)> { - let layout = self.square_layout()?; - // XXX Force layout to be Fortran (see #146) - match layout { - MatrixLayout::C { .. } => self.swap_axes(0, 1), - MatrixLayout::F { .. } => {} - } - let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?; - Ok((ArrayBase::from(s), self)) - } -} - -impl EighInplace for (ArrayBase, ArrayBase) -where - A: Scalar + Lapack, - S: DataMut, - S2: DataMut, -{ - type EigVal = Array1; - - /// Solves the generalized eigenvalue problem. - /// - /// # Panics - /// - /// Panics if the shapes of the matrices are different. - fn eigh_inplace(&mut self, uplo: UPLO) -> Result<(Self::EigVal, &mut Self)> { - assert_eq!( - self.0.shape(), - self.1.shape(), - "The shapes of the matrices must be identical.", - ); - let layout = self.0.square_layout()?; - // XXX Force layout to be Fortran (see #146) - match layout { - MatrixLayout::C { .. } => self.0.swap_axes(0, 1), - MatrixLayout::F { .. } => {} - } - - let layout = self.1.square_layout()?; - match layout { - MatrixLayout::C { .. } => self.1.swap_axes(0, 1), - MatrixLayout::F { .. } => {} - } - - let s = A::eigh_generalized( - true, - self.0.square_layout()?, - uplo, - self.0.as_allocated_mut()?, - self.1.as_allocated_mut()?, - )?; - - Ok((ArrayBase::from(s), self)) - } -} - -/// Calculate eigenvalues without eigenvectors -pub trait EigValsh { - type EigVal; - fn eigvalsh(&self, uplo: UPLO) -> Result; -} - -/// Calculate eigenvalues without eigenvectors -pub trait EigValshInto { - type EigVal; - fn eigvalsh_into(self, uplo: UPLO) -> Result; -} - -/// Calculate eigenvalues without eigenvectors -pub trait EigValshInplace { - type EigVal; - fn eigvalsh_inplace(&mut self, uplo: UPLO) -> Result; -} - -impl EigValshInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type EigVal = Array1; - - fn eigvalsh_into(mut self, uplo: UPLO) -> Result { - self.eigvalsh_inplace(uplo) - } -} - -impl EigValsh for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type EigVal = Array1; - - fn eigvalsh(&self, uplo: UPLO) -> Result { - let a = self.to_owned(); - a.eigvalsh_into(uplo) - } -} - -impl EigValshInplace for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type EigVal = Array1; - - fn eigvalsh_inplace(&mut self, uplo: UPLO) -> Result { - let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?; - Ok(ArrayBase::from(s)) - } -} - -/// Calculate symmetric square-root matrix using `eigh` -pub trait SymmetricSqrt { - type Output; - fn ssqrt(&self, uplo: UPLO) -> Result; -} - -impl SymmetricSqrt for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type Output = Array2; - - fn ssqrt(&self, uplo: UPLO) -> Result { - let a = self.to_owned(); - a.ssqrt_into(uplo) - } -} - -/// Calculate symmetric square-root matrix using `eigh` -pub trait SymmetricSqrtInto { - type Output; - fn ssqrt_into(self, uplo: UPLO) -> Result; -} - -impl SymmetricSqrtInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut + DataOwned, -{ - type Output = Array2; - - fn ssqrt_into(self, uplo: UPLO) -> Result { - let (e, v) = self.eigh_into(uplo)?; - let e_sqrt = Array::from_iter(e.iter().map(|r| Scalar::from_real(r.sqrt()))); - let ev = e_sqrt.into_diagonal().apply2(&v.t()); - Ok(v.apply2(&ev)) - } -} diff --git a/ndarray-linalg/src/error.rs b/ndarray-linalg/src/error.rs deleted file mode 100644 index c073b985..00000000 --- a/ndarray-linalg/src/error.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! Define Errors - -use ndarray::{Ixs, ShapeError}; -use thiserror::Error; - -pub type Result = ::std::result::Result; - -/// Master Error type of this crate -#[derive(Debug, Error)] -pub enum LinalgError { - /// Matrix is not square - #[error("Not square: rows({}) != cols({})", rows, cols)] - NotSquare { rows: i32, cols: i32 }, - - /// LAPACK subroutine returns non-zero code - #[error(transparent)] - Lapack(#[from] lax::error::Error), - - /// Strides of the array is not supported - #[error("invalid stride: s0={}, s1={}", s0, s1)] - InvalidStride { s0: Ixs, s1: Ixs }, - - /// Memory is not aligned continously - #[error("Memroy is not continously")] - MemoryNotCont, - - /// Obj cannot be made from a (rows, cols) matrix - #[error("{} cannot be made from a ({}, {}) matrix", obj, rows, cols)] - NotStandardShape { - obj: &'static str, - rows: i32, - cols: i32, - }, - - /// Strides of the array is not supported - #[error(transparent)] - Shape(#[from] ShapeError), -} diff --git a/ndarray-linalg/src/generate.rs b/ndarray-linalg/src/generate.rs deleted file mode 100644 index 5646c808..00000000 --- a/ndarray-linalg/src/generate.rs +++ /dev/null @@ -1,209 +0,0 @@ -//! Generator functions for matrices - -use ndarray::*; -use rand::prelude::*; - -use super::convert::*; -use super::error::*; -use super::qr::*; -use super::types::*; - -/// Hermite conjugate matrix -pub fn conjugate(a: &ArrayBase) -> ArrayBase -where - A: Scalar, - Si: Data, - So: DataOwned + DataMut, -{ - let mut a: ArrayBase = replicate(&a.t()); - for val in a.iter_mut() { - *val = val.conj(); - } - a -} - -/// Generate random array with given shape -/// -/// - This function uses [rand::thread_rng]. -/// See [random_using] for using another RNG -pub fn random(sh: Sh) -> ArrayBase -where - A: Scalar, - S: DataOwned, - D: Dimension, - Sh: ShapeBuilder, -{ - let mut rng = thread_rng(); - random_using(sh, &mut rng) -} - -/// Generate random array with given RNG -/// -/// - See [random] for using default RNG -pub fn random_using(sh: Sh, rng: &mut R) -> ArrayBase -where - A: Scalar, - S: DataOwned, - D: Dimension, - Sh: ShapeBuilder, - R: Rng, -{ - ArrayBase::from_shape_fn(sh, |_| A::rand(rng)) -} - -/// Generate random unitary matrix using QR decomposition -/// -/// - Be sure that this it **NOT** a uniform distribution. -/// Use it only for test purpose. -/// - This function uses [rand::thread_rng]. -/// See [random_unitary_using] for using another RNG. -pub fn random_unitary(n: usize) -> Array2 -where - A: Scalar + Lapack, -{ - let mut rng = thread_rng(); - random_unitary_using(n, &mut rng) -} - -/// Generate random unitary matrix using QR decomposition with given RNG -/// -/// - Be sure that this it **NOT** a uniform distribution. -/// Use it only for test purpose. -/// - See [random_unitary] for using default RNG. -pub fn random_unitary_using(n: usize, rng: &mut R) -> Array2 -where - A: Scalar + Lapack, - R: Rng, -{ - let a: Array2 = random_using((n, n), rng); - let (q, _r) = a.qr_into().unwrap(); - q -} - -/// Generate random regular matrix -/// -/// - Be sure that this it **NOT** a uniform distribution. -/// Use it only for test purpose. -/// - This function uses [rand::thread_rng]. -/// See [random_regular_using] for using another RNG. -pub fn random_regular(n: usize) -> Array2 -where - A: Scalar + Lapack, -{ - let mut rng = rand::thread_rng(); - random_regular_using(n, &mut rng) -} - -/// Generate random regular matrix with given RNG -/// -/// - Be sure that this it **NOT** a uniform distribution. -/// Use it only for test purpose. -/// - See [random_regular] for using default RNG. -pub fn random_regular_using(n: usize, rng: &mut R) -> Array2 -where - A: Scalar + Lapack, - R: Rng, -{ - let a: Array2 = random_using((n, n), rng); - let (q, mut r) = a.qr_into().unwrap(); - for i in 0..n { - r[(i, i)] = A::one() + A::from_real(r[(i, i)].abs()); - } - q.dot(&r) -} - -/// Random Hermite matrix -/// -/// - This function uses [rand::thread_rng]. -/// See [random_hermite_using] for using another RNG. -pub fn random_hermite(n: usize) -> ArrayBase -where - A: Scalar, - S: DataOwned + DataMut, -{ - let mut rng = rand::thread_rng(); - random_hermite_using(n, &mut rng) -} - -/// Random Hermite matrix with given RNG -/// -/// - See [random_hermite] for using default RNG. -pub fn random_hermite_using(n: usize, rng: &mut R) -> ArrayBase -where - A: Scalar, - S: DataOwned + DataMut, - R: Rng, -{ - let mut a: ArrayBase = random_using((n, n), rng); - for i in 0..n { - a[(i, i)] = a[(i, i)] + a[(i, i)].conj(); - for j in (i + 1)..n { - a[(i, j)] = a[(j, i)].conj(); - } - } - a -} - -/// Random Hermite Positive-definite matrix -/// -/// - Eigenvalue of matrix must be larger than 1 (thus non-singular) -/// - This function uses [rand::thread_rng]. -/// See [random_hpd_using] for using another RNG. -/// -pub fn random_hpd(n: usize) -> ArrayBase -where - A: Scalar, - S: DataOwned + DataMut, -{ - let mut rng = rand::thread_rng(); - random_hpd_using(n, &mut rng) -} - -/// Random Hermite Positive-definite matrix with given RNG -/// -/// - Eigenvalue of matrix must be larger than 1 (thus non-singular) -/// - See [random_hpd] for using default RNG. -/// -pub fn random_hpd_using(n: usize, rng: &mut R) -> ArrayBase -where - A: Scalar, - S: DataOwned + DataMut, - R: Rng, -{ - let a: Array2 = random_using((n, n), rng); - let ah: Array2 = conjugate(&a); - ArrayBase::eye(n) + &ah.dot(&a) -} - -/// construct matrix from diag -pub fn from_diag(d: &[A]) -> Array2 -where - A: Scalar, -{ - let n = d.len(); - let mut e = Array::zeros((n, n)); - for i in 0..n { - e[(i, i)] = d[i]; - } - e -} - -/// stack vectors into matrix horizontally -pub fn hstack(xs: &[ArrayBase]) -> Result> -where - A: Scalar, - S: Data, -{ - let views: Vec<_> = xs.iter().map(|x| x.view()).collect(); - stack(Axis(1), &views).map_err(Into::into) -} - -/// stack vectors into matrix vertically -pub fn vstack(xs: &[ArrayBase]) -> Result> -where - A: Scalar, - S: Data, -{ - let views: Vec<_> = xs.iter().map(|x| x.view()).collect(); - stack(Axis(0), &views).map_err(Into::into) -} diff --git a/ndarray-linalg/src/inner.rs b/ndarray-linalg/src/inner.rs deleted file mode 100644 index 87ca96cc..00000000 --- a/ndarray-linalg/src/inner.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::types::*; -use ndarray::*; - -/// Inner Product -/// -/// Differenct from `Dot` trait, this take complex conjugate of `self` elements -/// -pub trait InnerProduct { - type Elem: Scalar; - - /// Inner product `(self.conjugate, rhs) - fn inner(&self, rhs: &ArrayBase) -> Self::Elem - where - S: Data; -} - -impl InnerProduct for ArrayBase -where - A: Scalar, - S: Data, -{ - type Elem = A; - fn inner>(&self, rhs: &ArrayBase) -> A { - assert_eq!(self.len(), rhs.len()); - Zip::from(self) - .and(rhs) - .fold_while(A::zero(), |acc, s, r| { - FoldWhile::Continue(acc + s.conj() * *r) - }) - .into_inner() - } -} diff --git a/ndarray-linalg/src/krylov/arnoldi.rs b/ndarray-linalg/src/krylov/arnoldi.rs deleted file mode 100644 index 66c29991..00000000 --- a/ndarray-linalg/src/krylov/arnoldi.rs +++ /dev/null @@ -1,125 +0,0 @@ -//! Arnoldi iteration - -use super::*; -use crate::{norm::Norm, operator::LinearOperator}; -use num_traits::One; -use std::iter::*; - -/// Execute Arnoldi iteration as Rust iterator -/// -/// - [Arnoldi iteration - Wikipedia](https://en.wikipedia.org/wiki/Arnoldi_iteration) -/// -pub struct Arnoldi -where - A: Scalar, - S: DataMut, - F: LinearOperator, - Ortho: Orthogonalizer, -{ - a: F, - /// Next vector (normalized `|v|=1`) - v: ArrayBase, - /// Orthogonalizer - ortho: Ortho, - /// Coefficients to be composed into H-matrix - h: Vec>, -} - -impl Arnoldi -where - A: Scalar + Lapack, - S: DataMut, - F: LinearOperator, - Ortho: Orthogonalizer, -{ - /// Create an Arnoldi iterator from any linear operator `a` - pub fn new(a: F, mut v: ArrayBase, mut ortho: Ortho) -> Self { - assert_eq!(ortho.len(), 0); - assert!(ortho.tolerance() < One::one()); - // normalize before append because |v| may be smaller than ortho.tolerance() - let norm = v.norm_l2(); - azip!((v in &mut v) *v = v.div_real(norm)); - ortho.append(v.view()); - Arnoldi { - a, - v, - ortho, - h: Vec::new(), - } - } - - /// Dimension of Krylov subspace - pub fn dim(&self) -> usize { - self.ortho.len() - } - - /// Iterate until convergent - pub fn complete(mut self) -> (Q, H) { - for _ in &mut self {} // execute iteration until convergent - let q = self.ortho.get_q(); - let n = self.h.len(); - let mut h = Array2::zeros((n, n).f()); - for (i, hc) in self.h.iter().enumerate() { - let m = std::cmp::min(n, i + 2); - for j in 0..m { - h[(j, i)] = hc[j]; - } - } - (q, h) - } -} - -impl Iterator for Arnoldi -where - A: Scalar + Lapack, - S: DataMut, - F: LinearOperator, - Ortho: Orthogonalizer, -{ - type Item = Array1; - - fn next(&mut self) -> Option { - self.a.apply_mut(&mut self.v); - let result = self.ortho.div_append(&mut self.v); - let norm = self.v.norm_l2(); - azip!((v in &mut self.v) *v = v.div_real(norm)); - match result { - AppendResult::Added(coef) => { - self.h.push(coef.clone()); - Some(coef) - } - AppendResult::Dependent(coef) => { - self.h.push(coef); - None - } - } - } -} - -/// Utility to execute Arnoldi iteration with Householder reflection -pub fn arnoldi_householder( - a: impl LinearOperator, - v: ArrayBase, - tol: A::Real, -) -> (Q, H) -where - A: Scalar + Lapack, - S: DataMut, -{ - let householder = Householder::new(v.len(), tol); - Arnoldi::new(a, v, householder).complete() -} - -/// Utility to execute Arnoldi iteration with modified Gram-Schmit orthogonalizer -pub fn arnoldi_mgs( - a: impl LinearOperator, - v: ArrayBase, - tol: A::Real, -) -> (Q, H) -where - A: Scalar + Lapack, - S: DataMut, -{ - let mgs = MGS::new(v.len(), tol); - Arnoldi::new(a, v, mgs).complete() -} diff --git a/ndarray-linalg/src/krylov/householder.rs b/ndarray-linalg/src/krylov/householder.rs deleted file mode 100644 index c04d9049..00000000 --- a/ndarray-linalg/src/krylov/householder.rs +++ /dev/null @@ -1,247 +0,0 @@ -//! Householder reflection -//! -//! - [Householder transformation - Wikipedia](https://en.wikipedia.org/wiki/Householder_transformation) -//! - -use super::*; -use crate::{inner::*, norm::*}; -use num_traits::One; - -/// Calc a reflactor `w` from a vector `x` -pub fn calc_reflector(x: &mut ArrayBase) -where - A: Scalar + Lapack, - S: DataMut, -{ - assert!(!x.is_empty()); - let norm = x.norm_l2(); - let alpha = -x[0].mul_real(norm / x[0].abs()); - x[0] -= alpha; - let inv_rev_norm = A::Real::one() / x.norm_l2(); - azip!((a in x) *a = a.mul_real(inv_rev_norm)); -} - -/// Take a reflection `P = I - 2ww^T` -/// -/// Panic -/// ------ -/// - if the size of `w` and `a` mismaches -pub fn reflect(w: &ArrayBase, a: &mut ArrayBase) -where - A: Scalar + Lapack, - S1: Data, - S2: DataMut, -{ - assert_eq!(w.len(), a.len()); - let n = a.len(); - let c = A::from(2.0).unwrap() * w.inner(a); - for l in 0..n { - a[l] -= c * w[l]; - } -} - -/// Iterative orthogonalizer using Householder reflection -#[derive(Debug, Clone)] -pub struct Householder { - /// Dimension of orthogonalizer - dim: usize, - - /// Store Householder reflector. - /// - /// The coefficient is copied into another array, and this does not contain - v: Vec>, - - /// Tolerance - tol: A::Real, -} - -impl Householder { - /// Create a new orthogonalizer - pub fn new(dim: usize, tol: A::Real) -> Self { - Householder { - dim, - v: Vec::new(), - tol, - } - } - - /// Take a Reflection `P = I - 2ww^T` - fn fundamental_reflection(&self, k: usize, a: &mut ArrayBase) - where - S: DataMut, - { - assert!(k < self.v.len()); - assert_eq!( - a.len(), - self.dim, - "Input array size mismaches to the dimension" - ); - reflect(&self.v[k].slice(s![k..]), &mut a.slice_mut(s![k..])); - } - - /// Take forward reflection `P = P_l ... P_1` - pub fn forward_reflection(&self, a: &mut ArrayBase) - where - S: DataMut, - { - assert!(a.len() == self.dim); - let l = self.v.len(); - for k in 0..l { - self.fundamental_reflection(k, a); - } - } - - /// Take backward reflection `P = P_1 ... P_l` - pub fn backward_reflection(&self, a: &mut ArrayBase) - where - S: DataMut, - { - assert!(a.len() == self.dim); - let l = self.v.len(); - for k in (0..l).rev() { - self.fundamental_reflection(k, a); - } - } - - /// Compose coefficients array using reflected vector - fn compose_coefficients(&self, a: &ArrayBase) -> Coefficients - where - S: Data, - { - let k = self.len(); - let res = a.slice(s![k..]).norm_l2(); - let mut c = Array1::zeros(k + 1); - azip!((c in c.slice_mut(s![..k]), &a in a.slice(s![..k])) *c = a); - if k < a.len() { - let ak = a[k]; - c[k] = -ak.mul_real(res / ak.abs()); - } else { - c[k] = A::from_real(res); - } - c - } - - /// Construct the residual vector from reflected vector - fn construct_residual(&self, a: &mut ArrayBase) - where - S: DataMut, - { - let k = self.len(); - azip!((a in a.slice_mut(s![..k])) *a = A::zero()); - self.backward_reflection(a); - } -} - -impl Orthogonalizer for Householder { - type Elem = A; - - fn dim(&self) -> usize { - self.dim - } - - fn len(&self) -> usize { - self.v.len() - } - - fn tolerance(&self) -> A::Real { - self.tol - } - - fn decompose(&self, a: &mut ArrayBase) -> Array1 - where - S: DataMut, - { - self.forward_reflection(a); - let coef = self.compose_coefficients(a); - self.construct_residual(a); - coef - } - - fn coeff(&self, a: ArrayBase) -> Array1 - where - S: Data, - { - let mut a = a.into_owned(); - self.forward_reflection(&mut a); - self.compose_coefficients(&a) - } - - fn div_append(&mut self, a: &mut ArrayBase) -> AppendResult - where - S: DataMut, - { - assert_eq!(a.len(), self.dim); - let k = self.len(); - self.forward_reflection(a); - let coef = self.compose_coefficients(a); - if coef[k].abs() < self.tol { - return AppendResult::Dependent(coef); - } - calc_reflector(&mut a.slice_mut(s![k..])); - self.v.push(a.to_owned()); - self.construct_residual(a); - AppendResult::Added(coef) - } - - fn append(&mut self, a: ArrayBase) -> AppendResult - where - S: Data, - { - assert_eq!(a.len(), self.dim); - let mut a = a.into_owned(); - let k = self.len(); - self.forward_reflection(&mut a); - let coef = self.compose_coefficients(&a); - if coef[k].abs() < self.tol { - return AppendResult::Dependent(coef); - } - calc_reflector(&mut a.slice_mut(s![k..])); - self.v.push(a.to_owned()); - AppendResult::Added(coef) - } - - fn get_q(&self) -> Q { - assert!(self.len() > 0); - let mut a = Array::zeros((self.dim(), self.len())); - for (i, mut col) in a.axis_iter_mut(Axis(1)).enumerate() { - col[i] = A::one(); - self.backward_reflection(&mut col); - } - a - } -} - -/// Online QR decomposition using Householder reflection -pub fn householder( - iter: impl Iterator>, - dim: usize, - rtol: A::Real, - strategy: Strategy, -) -> (Q, R) -where - A: Scalar + Lapack, - S: Data, -{ - let h = Householder::new(dim, rtol); - qr(iter, h, strategy) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::assert::*; - use num_traits::Zero; - - #[test] - fn check_reflector() { - let mut a = array![c64::new(1.0, 1.0), c64::new(1.0, 0.0), c64::new(0.0, 1.0)]; - let mut w = a.clone(); - calc_reflector(&mut w); - reflect(&w, &mut a); - close_l2( - &a, - &array![-c64::new(2.0.sqrt(), 2.0.sqrt()), c64::zero(), c64::zero()], - 1e-9, - ); - } -} diff --git a/ndarray-linalg/src/krylov/mgs.rs b/ndarray-linalg/src/krylov/mgs.rs deleted file mode 100644 index 67806a2c..00000000 --- a/ndarray-linalg/src/krylov/mgs.rs +++ /dev/null @@ -1,114 +0,0 @@ -//! Modified Gram-Schmit orthogonalizer - -use super::*; -use crate::{generate::*, inner::*, norm::Norm}; - -/// Iterative orthogonalizer using modified Gram-Schmit procedure -#[derive(Debug, Clone)] -pub struct MGS { - /// Dimension of base space - dim: usize, - - /// Basis of spanned space - q: Vec>, - - /// Tolerance - tol: A::Real, -} - -impl MGS { - /// Create an empty orthogonalizer - pub fn new(dim: usize, tol: A::Real) -> Self { - Self { - dim, - q: Vec::new(), - tol, - } - } -} - -impl Orthogonalizer for MGS { - type Elem = A; - - fn dim(&self) -> usize { - self.dim - } - - fn len(&self) -> usize { - self.q.len() - } - - fn tolerance(&self) -> A::Real { - self.tol - } - - fn decompose(&self, a: &mut ArrayBase) -> Array1 - where - S: DataMut, - { - assert_eq!(a.len(), self.dim()); - let mut coef = Array1::zeros(self.len() + 1); - for i in 0..self.len() { - let q = &self.q[i]; - let c = q.inner(a); - azip!((a in &mut *a, &q in q) *a -= c * q); - coef[i] = c; - } - let nrm = a.norm_l2(); - coef[self.len()] = A::from_real(nrm); - coef - } - - fn coeff(&self, a: ArrayBase) -> Array1 - where - A: Lapack, - S: Data, - { - let mut a = a.into_owned(); - self.decompose(&mut a) - } - - fn append(&mut self, a: ArrayBase) -> AppendResult - where - A: Lapack, - S: Data, - { - let mut a = a.into_owned(); - self.div_append(&mut a) - } - - fn div_append(&mut self, a: &mut ArrayBase) -> AppendResult - where - A: Lapack, - S: DataMut, - { - let coef = self.decompose(a); - let nrm = coef[coef.len() - 1].re(); - if nrm < self.tol { - // Linearly dependent - return AppendResult::Dependent(coef); - } - azip!((a in &mut *a) *a /= A::from_real(nrm)); - self.q.push(a.to_owned()); - AppendResult::Added(coef) - } - - fn get_q(&self) -> Q { - hstack(&self.q).unwrap() - } -} - -/// Online QR decomposition using modified Gram-Schmit algorithm -pub fn mgs( - iter: impl Iterator>, - dim: usize, - rtol: A::Real, - strategy: Strategy, -) -> (Q, R) -where - A: Scalar + Lapack, - S: Data, -{ - let mgs = MGS::new(dim, rtol); - qr(iter, mgs, strategy) -} diff --git a/ndarray-linalg/src/krylov/mod.rs b/ndarray-linalg/src/krylov/mod.rs deleted file mode 100644 index 14c9f7ef..00000000 --- a/ndarray-linalg/src/krylov/mod.rs +++ /dev/null @@ -1,211 +0,0 @@ -//! Krylov subspace methods - -use crate::types::*; -use ndarray::*; - -pub mod arnoldi; -pub mod householder; -pub mod mgs; - -pub use arnoldi::{arnoldi_householder, arnoldi_mgs, Arnoldi}; -pub use householder::{householder, Householder}; -pub use mgs::{mgs, MGS}; - -/// Q-matrix -/// -/// - Maybe **NOT** square -/// - Unitary for existing columns -/// -pub type Q = Array2; - -/// R-matrix -/// -/// - Maybe **NOT** square -/// - Upper triangle -/// -pub type R = Array2; - -/// H-matrix -/// -/// - Maybe **NOT** square -/// - Hessenberg matrix -/// -pub type H = Array2; - -/// Array type for coefficients to the current basis -/// -/// - The length must be `self.len() + 1` -/// - Last component is the residual norm -/// -pub type Coefficients = Array1; - -/// Trait for creating orthogonal basis from iterator of arrays -/// -/// Panic -/// ------- -/// - if the size of the input array mismatches to the dimension -/// -/// Example -/// ------- -/// -/// ```rust -/// # use ndarray::*; -/// # use ndarray_linalg::{krylov::*, *}; -/// let mut mgs = MGS::new(3, 1e-9); -/// let coef = mgs.append(array![0.0, 1.0, 0.0]).into_coeff(); -/// close_l2(&coef, &array![1.0], 1e-9); -/// -/// let coef = mgs.append(array![1.0, 1.0, 0.0]).into_coeff(); -/// close_l2(&coef, &array![1.0, 1.0], 1e-9); -/// -/// // Fail if the vector is linearly dependent -/// assert!(mgs.append(array![1.0, 2.0, 0.0]).is_dependent()); -/// -/// // You can get coefficients of dependent vector -/// if let AppendResult::Dependent(coef) = mgs.append(array![1.0, 2.0, 0.0]) { -/// close_l2(&coef, &array![2.0, 1.0, 0.0], 1e-9); -/// } -/// ``` -pub trait Orthogonalizer { - type Elem: Scalar; - - /// Dimension of input array - fn dim(&self) -> usize; - - /// Number of cached basis - fn len(&self) -> usize; - - /// check if the basis spans entire space - fn is_full(&self) -> bool { - self.len() == self.dim() - } - - fn is_empty(&self) -> bool { - self.len() == 0 - } - - fn tolerance(&self) -> ::Real; - - /// Decompose given vector into the span of current basis and - /// its tangent space - /// - /// - `a` becomes the tangent vector - /// - The Coefficients to the current basis is returned. - /// - fn decompose(&self, a: &mut ArrayBase) -> Coefficients - where - S: DataMut; - - /// Calculate the coefficient to the current basis basis - /// - /// - This will be faster than `decompose` because the construction of the residual vector may - /// requires more Calculation - /// - fn coeff(&self, a: ArrayBase) -> Coefficients - where - S: Data; - - /// Add new vector if the residual is larger than relative tolerance - fn append(&mut self, a: ArrayBase) -> AppendResult - where - S: Data; - - /// Add new vector if the residual is larger than relative tolerance, - /// and return the residual vector - fn div_append(&mut self, a: &mut ArrayBase) -> AppendResult - where - S: DataMut; - - /// Get Q-matrix of generated basis - fn get_q(&self) -> Q; -} - -pub enum AppendResult { - Added(Coefficients), - Dependent(Coefficients), -} - -impl AppendResult { - pub fn into_coeff(self) -> Coefficients { - match self { - AppendResult::Added(c) => c, - AppendResult::Dependent(c) => c, - } - } - - pub fn is_dependent(&self) -> bool { - match self { - AppendResult::Added(_) => false, - AppendResult::Dependent(_) => true, - } - } - - pub fn coeff(&self) -> &Coefficients { - match self { - AppendResult::Added(c) => c, - AppendResult::Dependent(c) => c, - } - } - - pub fn residual_norm(&self) -> A::Real { - let c = self.coeff(); - c[c.len() - 1].abs() - } -} - -/// Strategy for linearly dependent vectors appearing in iterative QR decomposition -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Strategy { - /// Terminate iteration if dependent vector comes - Terminate, - - /// Skip dependent vector - Skip, - - /// Orthogonalize dependent vector without adding to Q, - /// i.e. R must be non-square like following: - /// - /// ```text - /// x x x x x - /// 0 x x x x - /// 0 0 0 x x - /// 0 0 0 0 x - /// ``` - Full, -} - -/// Online QR decomposition using arbitrary orthogonalizer -pub fn qr( - iter: impl Iterator>, - mut ortho: impl Orthogonalizer, - strategy: Strategy, -) -> (Q, R) -where - A: Scalar + Lapack, - S: Data, -{ - assert_eq!(ortho.len(), 0); - - let mut coefs = Vec::new(); - for a in iter { - match ortho.append(a.into_owned()) { - AppendResult::Added(coef) => coefs.push(coef), - AppendResult::Dependent(coef) => match strategy { - Strategy::Terminate => break, - Strategy::Skip => continue, - Strategy::Full => coefs.push(coef), - }, - } - } - let n = ortho.len(); - let m = coefs.len(); - let mut r = Array2::zeros((n, m).f()); - for j in 0..m { - for i in 0..n { - if i < coefs[j].len() { - r[(i, j)] = coefs[j][i]; - } - } - } - (ortho.get_q(), r) -} diff --git a/ndarray-linalg/src/layout.rs b/ndarray-linalg/src/layout.rs deleted file mode 100644 index d0d13585..00000000 --- a/ndarray-linalg/src/layout.rs +++ /dev/null @@ -1,83 +0,0 @@ -//! Convert ndarray into LAPACK-compatible matrix format - -use super::error::*; -use ndarray::*; - -pub use lax::layout::MatrixLayout; - -pub trait AllocatedArray { - type Elem; - fn layout(&self) -> Result; - fn square_layout(&self) -> Result; - /// Returns Ok iff the matrix is square (without computing the layout). - fn ensure_square(&self) -> Result<()>; - fn as_allocated(&self) -> Result<&[Self::Elem]>; -} - -pub trait AllocatedArrayMut: AllocatedArray { - fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>; -} - -impl AllocatedArray for ArrayBase -where - S: Data, -{ - type Elem = A; - - fn layout(&self) -> Result { - let shape = self.shape(); - let strides = self.strides(); - if shape[0] == strides[1] as usize { - return Ok(MatrixLayout::F { - col: self.ncols() as i32, - lda: self.nrows() as i32, - }); - } - if shape[1] == strides[0] as usize { - return Ok(MatrixLayout::C { - row: self.nrows() as i32, - lda: self.ncols() as i32, - }); - } - Err(LinalgError::InvalidStride { - s0: strides[0], - s1: strides[1], - }) - } - - fn square_layout(&self) -> Result { - let l = self.layout()?; - let (n, m) = l.size(); - if n == m { - Ok(l) - } else { - Err(LinalgError::NotSquare { rows: n, cols: m }) - } - } - - fn ensure_square(&self) -> Result<()> { - if self.is_square() { - Ok(()) - } else { - Err(LinalgError::NotSquare { - rows: self.nrows() as i32, - cols: self.ncols() as i32, - }) - } - } - - fn as_allocated(&self) -> Result<&[A]> { - self.as_slice_memory_order() - .ok_or(LinalgError::MemoryNotCont) - } -} - -impl AllocatedArrayMut for ArrayBase -where - S: DataMut, -{ - fn as_allocated_mut(&mut self) -> Result<&mut [A]> { - self.as_slice_memory_order_mut() - .ok_or(LinalgError::MemoryNotCont) - } -} diff --git a/ndarray-linalg/src/least_squares.rs b/ndarray-linalg/src/least_squares.rs deleted file mode 100644 index f376f569..00000000 --- a/ndarray-linalg/src/least_squares.rs +++ /dev/null @@ -1,599 +0,0 @@ -//! # Least Squares -//! -//! Compute a least-squares solution to the equation Ax = b. -//! Compute a vector x such that the 2-norm ``|b - A x|`` is minimized. -//! -//! Finding the least squares solutions is implemented as traits, meaning -//! that to solve `A x = b` for a matrix `A` and a RHS `b`, we call -//! `let result = A.least_squares(&b);`. This returns a `result` of -//! type `LeastSquaresResult`, the solution for the least square problem -//! is in `result.solution`. -//! -//! There are three traits, `LeastSquaresSvd` with the method `least_squares`, -//! which operates on immutable references, `LeastSquaresInto` with the method -//! `least_squares_into`, which takes ownership over both the array `A` and the -//! RHS `b` and `LeastSquaresSvdInPlace` with the method `least_squares_in_place`, -//! which operates on mutable references for `A` and `b` and destroys these when -//! solving the least squares problem. `LeastSquaresSvdInto` and -//! `LeastSquaresSvdInPlace` avoid an extra allocation for `A` and `b` which -//! `LeastSquaresSvd` has do perform to preserve the values in `A` and `b`. -//! -//! All methods use the Lapacke family of methods `*gelsd` which solves the least -//! squares problem using the SVD with a divide-and-conquer strategy. -//! -//! The traits are implemented for value types `f32`, `f64`, `c32` and `c64` -//! and vector or matrix right-hand-sides (`ArrayBase` or `ArrayBase`). -//! -//! ## Example -//! ```rust -//! use approx::AbsDiffEq; // for abs_diff_eq -//! use ndarray::{array, Array1, Array2}; -//! use ndarray_linalg::{LeastSquaresSvd, LeastSquaresSvdInto, LeastSquaresSvdInPlace}; -//! -//! let a: Array2 = array![ -//! [1., 1., 1.], -//! [2., 3., 4.], -//! [3., 5., 2.], -//! [4., 2., 5.], -//! [5., 4., 3.] -//! ]; -//! // solving for a single right-hand side -//! let b: Array1 = array![-10., 12., 14., 16., 18.]; -//! let expected: Array1 = array![2., 1., 1.]; -//! let result = a.least_squares(&b).unwrap(); -//! assert!(result.solution.abs_diff_eq(&expected, 1e-12)); -//! -//! // solving for two right-hand sides at once -//! let b_2: Array2 = -//! array![[-10., -3.], [12., 14.], [14., 12.], [16., 16.], [18., 16.]]; -//! let expected_2: Array2 = array![[2., 1.], [1., 1.], [1., 2.]]; -//! let result_2 = a.least_squares(&b_2).unwrap(); -//! assert!(result_2.solution.abs_diff_eq(&expected_2, 1e-12)); -//! -//! // using `least_squares_in_place` which overwrites its arguments -//! let mut a_3 = a.clone(); -//! let mut b_3 = b.clone(); -//! let result_3 = a_3.least_squares_in_place(&mut b_3).unwrap(); -//! -//! // using `least_squares_into` which consumes its arguments -//! let result_4 = a.least_squares_into(b).unwrap(); -//! // `a` and `b` have been moved, no longer valid -//! ``` - -use lax::*; -use ndarray::*; - -use crate::error::*; -use crate::layout::*; -use crate::types::*; - -/// Result of a LeastSquares computation -/// -/// Takes two type parameters, `E`, the element type of the matrix -/// (one of `f32`, `f64`, `c32` or `c64`) and `I`, the dimension of -/// b in the equation `Ax = b` (one of `Ix1` or `Ix2`). If `I` is `Ix1`, -/// the right-hand-side (RHS) is a `n x 1` column vector and the solution -/// is a `m x 1` column vector. If `I` is `Ix2`, the RHS is a `n x k` matrix -/// (which can be seen as solving `Ax = b` k times for different b) and -/// the solution is a `m x k` matrix. -#[derive(Debug, Clone)] -pub struct LeastSquaresResult { - /// The singular values of the matrix A in `Ax = b` - pub singular_values: Array1, - /// The solution vector or matrix `x` which is the best - /// solution to `Ax = b`, i.e. minimizing the 2-norm `||b - Ax||` - pub solution: Array, - /// The rank of the matrix A in `Ax = b` - pub rank: i32, - /// If n < m and rank(A) == n, the sum of squares - /// If b is a (m x 1) vector, this is a 0-dimensional array (single value) - /// If b is a (m x k) matrix, this is a (k x 1) column vector - pub residual_sum_of_squares: Option>, -} -/// Solve least squares for immutable references -pub trait LeastSquaresSvd -where - D: Data, - E: Scalar + Lapack, - I: Dimension, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(&rhs)`. `A` and `rhs` - /// are unchanged. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares(&self, rhs: &ArrayBase) -> Result>; -} - -/// Solve least squares for owned matrices -pub trait LeastSquaresSvdInto -where - D: Data, - E: Scalar + Lapack, - I: Dimension, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(rhs)`, consuming both `A` - /// and `rhs`. This uses the memory location of `A` and - /// `rhs`, which avoids some extra memory allocations. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares_into(self, rhs: ArrayBase) -> Result>; -} - -/// Solve least squares for mutable references, overwriting -/// the input fields in the process -pub trait LeastSquaresSvdInPlace -where - D: Data, - E: Scalar + Lapack, - I: Dimension, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(&mut rhs)`, overwriting both `A` - /// and `rhs`. This uses the memory location of `A` and - /// `rhs`, which avoids some extra memory allocations. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares_in_place( - &mut self, - rhs: &mut ArrayBase, - ) -> Result>; -} - -/// Solve least squares for immutable references and a single -/// column vector as a right-hand side. -/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any -/// valid representation for `ArrayBase` (over `E`). -impl LeastSquaresSvd for ArrayBase -where - E: Scalar + Lapack, - D1: Data, - D2: Data, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(&rhs)`, where `rhs` is a - /// single column vector. `A` and `rhs` are unchanged. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares(&self, rhs: &ArrayBase) -> Result> { - let a = self.to_owned(); - let b = rhs.to_owned(); - a.least_squares_into(b) - } -} - -/// Solve least squares for immutable references and matrix -/// (=mulitipe vectors) as a right-hand side. -/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any -/// valid representation for `ArrayBase` (over `E`). -impl LeastSquaresSvd for ArrayBase -where - E: Scalar + Lapack, - D1: Data, - D2: Data, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(&rhs)`, where `rhs` is - /// matrix. `A` and `rhs` are unchanged. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares(&self, rhs: &ArrayBase) -> Result> { - let a = self.to_owned(); - let b = rhs.to_owned(); - a.least_squares_into(b) - } -} - -/// Solve least squares for owned values and a single -/// column vector as a right-hand side. The matrix and the RHS -/// vector are consumed. -/// -/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D` can be any -/// valid representation for `ArrayBase`. -impl LeastSquaresSvdInto for ArrayBase -where - E: Scalar + Lapack, - D1: DataMut, - D2: DataMut, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(rhs)`, where `rhs` is a - /// single column vector. `A` and `rhs` are consumed. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares_into( - mut self, - mut rhs: ArrayBase, - ) -> Result> { - self.least_squares_in_place(&mut rhs) - } -} - -/// Solve least squares for owned values and a matrix -/// as a right-hand side. The matrix and the RHS matrix -/// are consumed. -/// -/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any -/// valid representation for `ArrayBase` (over `E`). -impl LeastSquaresSvdInto for ArrayBase -where - E: Scalar + Lapack, - D1: DataMut, - D2: DataMut, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(rhs)`, where `rhs` is a - /// matrix. `A` and `rhs` are consumed. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares_into( - mut self, - mut rhs: ArrayBase, - ) -> Result> { - self.least_squares_in_place(&mut rhs) - } -} - -/// Solve least squares for mutable references and a vector -/// as a right-hand side. Both values are overwritten in the -/// call. -/// -/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any -/// valid representation for `ArrayBase` (over `E`). -impl LeastSquaresSvdInPlace for ArrayBase -where - E: Scalar + Lapack, - D1: DataMut, - D2: DataMut, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(rhs)`, where `rhs` is a - /// vector. `A` and `rhs` are overwritten in the call. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares_in_place( - &mut self, - rhs: &mut ArrayBase, - ) -> Result> { - if self.shape()[0] != rhs.shape()[0] { - return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape).into()); - } - let (m, n) = (self.shape()[0], self.shape()[1]); - if n > m { - // we need a new rhs b/c it will be overwritten with the solution - // for which we need `n` entries - let mut new_rhs = Array1::::zeros((n,)); - new_rhs.slice_mut(s![0..m]).assign(rhs); - compute_least_squares_srhs(self, &mut new_rhs) - } else { - compute_least_squares_srhs(self, rhs) - } - } -} - -fn compute_least_squares_srhs( - a: &mut ArrayBase, - rhs: &mut ArrayBase, -) -> Result> -where - E: Scalar + Lapack, - D1: DataMut, - D2: DataMut, -{ - let LeastSquaresOwned:: { - singular_values, - rank, - } = E::least_squares( - a.layout()?, - a.as_allocated_mut()?, - rhs.as_slice_memory_order_mut() - .ok_or(LinalgError::MemoryNotCont)?, - )?; - - let (m, n) = (a.shape()[0], a.shape()[1]); - let solution = rhs.slice(s![0..n]).to_owned(); - let residual_sum_of_squares = compute_residual_scalar(m, n, rank, rhs); - Ok(LeastSquaresResult { - solution, - singular_values: Array::from_shape_vec((singular_values.len(),), singular_values)?, - rank, - residual_sum_of_squares, - }) -} - -fn compute_residual_scalar>( - m: usize, - n: usize, - rank: i32, - b: &ArrayBase, -) -> Option> { - if m < n || n != rank as usize { - return None; - } - let mut arr: Array = Array::zeros(()); - arr[()] = b.slice(s![n..]).mapv(|x| x.powi(2).abs()).sum(); - Some(arr) -} - -/// Solve least squares for mutable references and a matrix -/// as a right-hand side. Both values are overwritten in the -/// call. -/// -/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any -/// valid representation for `ArrayBase` (over `E`). -impl LeastSquaresSvdInPlace for ArrayBase -where - E: Scalar + Lapack, - D1: DataMut, - D2: DataMut, -{ - /// Solve a least squares problem of the form `Ax = rhs` - /// by calling `A.least_squares(rhs)`, where `rhs` is a - /// matrix. `A` and `rhs` are overwritten in the call. - /// - /// `A` and `rhs` must have the same layout, i.e. they must - /// be both either row- or column-major format, otherwise a - /// `IncompatibleShape` error is raised. - fn least_squares_in_place( - &mut self, - rhs: &mut ArrayBase, - ) -> Result> { - if self.shape()[0] != rhs.shape()[0] { - return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape).into()); - } - let (m, n) = (self.shape()[0], self.shape()[1]); - if n > m { - // we need a new rhs b/c it will be overwritten with the solution - // for which we need `n` entries - let k = rhs.shape()[1]; - let mut new_rhs = match self.layout()? { - MatrixLayout::C { .. } => Array2::::zeros((n, k)), - MatrixLayout::F { .. } => Array2::::zeros((n, k).f()), - }; - new_rhs.slice_mut(s![0..m, ..]).assign(rhs); - compute_least_squares_nrhs(self, &mut new_rhs) - } else { - compute_least_squares_nrhs(self, rhs) - } - } -} - -fn compute_least_squares_nrhs( - a: &mut ArrayBase, - rhs: &mut ArrayBase, -) -> Result> -where - E: Scalar + Lapack, - D1: DataMut, - D2: DataMut, -{ - let a_layout = a.layout()?; - let rhs_layout = rhs.layout()?; - let LeastSquaresOwned:: { - singular_values, - rank, - } = E::least_squares_nrhs( - a_layout, - a.as_allocated_mut()?, - rhs_layout, - rhs.as_allocated_mut()?, - )?; - - let solution: Array2 = rhs.slice(s![..a.shape()[1], ..]).to_owned(); - let singular_values = Array::from_shape_vec((singular_values.len(),), singular_values)?; - let (m, n) = (a.shape()[0], a.shape()[1]); - let residual_sum_of_squares = compute_residual_array1(m, n, rank, rhs); - Ok(LeastSquaresResult { - solution, - singular_values, - rank, - residual_sum_of_squares, - }) -} - -fn compute_residual_array1>( - m: usize, - n: usize, - rank: i32, - b: &ArrayBase, -) -> Option> { - if m < n || n != rank as usize { - return None; - } - Some( - b.slice(s![n.., ..]) - .mapv(|x| x.powi(2).abs()) - .sum_axis(Axis(0)), - ) -} - -#[cfg(test)] -mod tests { - use crate::{error::LinalgError, *}; - use approx::AbsDiffEq; - use ndarray::*; - - // - // Test that the different least squares traits work as intended on the - // different array types. - // - // | least_squares | ls_into | ls_in_place | - // --------------+---------------+---------+-------------+ - // Array | yes | yes | yes | - // ArcArray | yes | no | no | - // CowArray | yes | yes | yes | - // ArrayView | yes | no | no | - // ArrayViewMut | yes | no | yes | - // - - fn assert_result, D2: Data>( - a: &ArrayBase, - b: &ArrayBase, - res: &LeastSquaresResult, - ) { - assert_eq!(res.rank, 2); - let b_hat = a.dot(&res.solution); - let rssq = (b - &b_hat).mapv(|x| x.powi(2)).sum(); - assert!(res.residual_sum_of_squares.as_ref().unwrap()[()].abs_diff_eq(&rssq, 1e-12)); - assert!(res - .solution - .abs_diff_eq(&array![-0.428571428571429, 0.85714285714285], 1e-12)); - } - - #[test] - fn on_arc() { - let a: ArcArray2 = array![[1., 2.], [4., 5.], [3., 4.]].into_shared(); - let b: ArcArray1 = array![1., 2., 3.].into_shared(); - let res = a.least_squares(&b).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn on_cow() { - let a = CowArray::from(array![[1., 2.], [4., 5.], [3., 4.]]); - let b = CowArray::from(array![1., 2., 3.]); - let res = a.least_squares(&b).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn on_view() { - let a: Array2 = array![[1., 2.], [4., 5.], [3., 4.]]; - let b: Array1 = array![1., 2., 3.]; - let av = a.view(); - let bv = b.view(); - let res = av.least_squares(&bv).unwrap(); - assert_result(&av, &bv, &res); - } - - #[test] - fn on_view_mut() { - let mut a: Array2 = array![[1., 2.], [4., 5.], [3., 4.]]; - let mut b: Array1 = array![1., 2., 3.]; - let av = a.view_mut(); - let bv = b.view_mut(); - let res = av.least_squares(&bv).unwrap(); - assert_result(&av, &bv, &res); - } - - #[test] - fn on_cow_view() { - let a = CowArray::from(array![[1., 2.], [4., 5.], [3., 4.]]); - let b: Array1 = array![1., 2., 3.]; - let bv = b.view(); - let res = a.least_squares(&bv).unwrap(); - assert_result(&a, &bv, &res); - } - - #[test] - fn into_on_owned() { - let a: Array2 = array![[1., 2.], [4., 5.], [3., 4.]]; - let b: Array1 = array![1., 2., 3.]; - let ac = a.clone(); - let bc = b.clone(); - let res = ac.least_squares_into(bc).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn into_on_arc() { - let a: ArcArray2 = array![[1., 2.], [4., 5.], [3., 4.]].into_shared(); - let b: ArcArray1 = array![1., 2., 3.].into_shared(); - let a2 = a.clone(); - let b2 = b.clone(); - let res = a2.least_squares_into(b2).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn into_on_cow() { - let a = CowArray::from(array![[1., 2.], [4., 5.], [3., 4.]]); - let b = CowArray::from(array![1., 2., 3.]); - let a2 = a.clone(); - let b2 = b.clone(); - let res = a2.least_squares_into(b2).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn into_on_owned_cow() { - let a: Array2 = array![[1., 2.], [4., 5.], [3., 4.]]; - let b = CowArray::from(array![1., 2., 3.]); - let ac = a.clone(); - let b2 = b.clone(); - let res = ac.least_squares_into(b2).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn in_place_on_owned() { - let a = array![[1., 2.], [4., 5.], [3., 4.]]; - let b = array![1., 2., 3.]; - let mut a2 = a.clone(); - let mut b2 = b.clone(); - let res = a2.least_squares_in_place(&mut b2).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn in_place_on_cow() { - let a = CowArray::from(array![[1., 2.], [4., 5.], [3., 4.]]); - let b = CowArray::from(array![1., 2., 3.]); - let mut a2 = a.clone(); - let mut b2 = b.clone(); - let res = a2.least_squares_in_place(&mut b2).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn in_place_on_mut_view() { - let a = array![[1., 2.], [4., 5.], [3., 4.]]; - let b = array![1., 2., 3.]; - let mut a2 = a.clone(); - let mut b2 = b.clone(); - let av = &mut a2.view_mut(); - let bv = &mut b2.view_mut(); - let res = av.least_squares_in_place(bv).unwrap(); - assert_result(&a, &b, &res); - } - - #[test] - fn in_place_on_owned_cow() { - let a = array![[1., 2.], [4., 5.], [3., 4.]]; - let b = CowArray::from(array![1., 2., 3.]); - let mut a2 = a.clone(); - let mut b2 = b.clone(); - let res = a2.least_squares_in_place(&mut b2).unwrap(); - assert_result(&a, &b, &res); - } - - // - // Testing error cases - // - #[test] - fn incompatible_shape_error_on_mismatching_num_rows() { - let a: Array2 = array![[1., 2.], [4., 5.], [3., 4.]]; - let b: Array1 = array![1., 2.]; - match a.least_squares(&b) { - Err(LinalgError::Shape(e)) if e.kind() == ErrorKind::IncompatibleShape => {} - _ => panic!("Should be raise IncompatibleShape"), - } - } -} diff --git a/ndarray-linalg/src/lib.rs b/ndarray-linalg/src/lib.rs deleted file mode 100644 index 784e1dff..00000000 --- a/ndarray-linalg/src/lib.rs +++ /dev/null @@ -1,100 +0,0 @@ -//! The `ndarray-linalg` crate provides linear algebra functionalities for `ArrayBase`, the n-dimensional array data structure provided by [`ndarray`](https://github.com/rust-ndarray/ndarray). -//! -//! `ndarray-linalg` leverages [LAPACK](http://www.netlib.org/lapack/)'s routines using the bindings provided by [blas-lapack-rs/lapack](https://github.com/blas-lapack-rs/lapack). -//! -//! Linear algebra methods -//! ----------------------- -//! - Decomposition methods: -//! - [QR decomposition](qr/index.html) -//! - [Cholesky/LU decomposition](cholesky/index.html) -//! - [Eigenvalue decomposition](eig/index.html) -//! - [Eigenvalue decomposition for Hermite matrices](eigh/index.html) -//! - [**S**ingular **V**alue **D**ecomposition](svd/index.html) -//! - Solution of linear systems: -//! - [General matrices](solve/index.html) -//! - [Triangular matrices](triangular/index.html) -//! - [Hermitian/real symmetric matrices](solveh/index.html) -//! - [Tridiagonal matrices](tridiagonal/index.html) -//! - [Inverse matrix computation](solve/trait.Inverse.html) -//! -//! Naming Convention -//! ----------------------- -//! Each routine is usually exposed as a trait, implemented by the relevant types. -//! -//! For each routine there might be multiple "variants": different traits corresponding to the different ownership possibilities of the array you intend to work on. -//! -//! For example, if you are interested in the QR decomposition of a square matrix, you can use: -//! - [QRSquare](qr/trait.QRSquare.html), if you hold an immutable reference (i.e. `&self`) to the matrix you want to decompose; -//! - [QRSquareInplace](qr/trait.QRSquareInplace.html), if you hold a mutable reference (i.e. `&mut self`) to the matrix you want to decompose; -//! - [QRSquareInto](qr/trait.QRSquareInto.html), if you can pass the matrix you want to decompose by value (e.g. `self`). -//! -//! Depending on the algorithm, each variant might require more or less copy operations of the underlying data. -//! -//! Details are provided in the description of each routine. -//! -//! Utilities -//! ----------- -//! - [Assertions for array](index.html#macros) -//! - [Random matrix generators](generate/index.html) -//! - [Scalar trait](types/trait.Scalar.html) - -#![allow( - clippy::module_inception, - clippy::many_single_char_names, - clippy::type_complexity, - clippy::ptr_arg -)] -#![deny(rustdoc::broken_intra_doc_links, rustdoc::private_intra_doc_links)] - -#[macro_use] -extern crate ndarray; - -pub mod assert; -pub mod cholesky; -pub mod convert; -pub mod diagonal; -pub mod eig; -pub mod eigh; -pub mod error; -pub mod generate; -pub mod inner; -pub mod krylov; -pub mod layout; -pub mod least_squares; -pub mod lobpcg; -pub mod norm; -pub mod operator; -pub mod opnorm; -pub mod qr; -pub mod solve; -pub mod solveh; -pub mod svd; -pub mod svddc; -pub mod trace; -pub mod triangular; -pub mod tridiagonal; -pub mod types; - -pub use crate::assert::*; -pub use crate::cholesky::*; -pub use crate::convert::*; -pub use crate::diagonal::*; -pub use crate::eig::*; -pub use crate::eigh::*; -pub use crate::generate::*; -pub use crate::inner::*; -pub use crate::layout::*; -pub use crate::least_squares::*; -pub use crate::lobpcg::{TruncatedEig, TruncatedOrder, TruncatedSvd}; -pub use crate::norm::*; -pub use crate::operator::*; -pub use crate::opnorm::*; -pub use crate::qr::*; -pub use crate::solve::*; -pub use crate::solveh::*; -pub use crate::svd::*; -pub use crate::svddc::*; -pub use crate::trace::*; -pub use crate::triangular::*; -pub use crate::tridiagonal::*; -pub use crate::types::*; diff --git a/ndarray-linalg/src/lobpcg/eig.rs b/ndarray-linalg/src/lobpcg/eig.rs deleted file mode 100644 index 7349c36d..00000000 --- a/ndarray-linalg/src/lobpcg/eig.rs +++ /dev/null @@ -1,199 +0,0 @@ -use super::lobpcg::{lobpcg, LobpcgResult, Order}; -use crate::{generate, Scalar}; -use lax::Lapack; - -///! Implements truncated eigenvalue decomposition -/// -use ndarray::prelude::*; -use ndarray::stack; -use ndarray::ScalarOperand; -use num_traits::{Float, NumCast}; - -/// Truncated eigenproblem solver -/// -/// This struct wraps the LOBPCG algorithm and provides convenient builder-pattern access to -/// parameter like maximal iteration, precision and constraint matrix. Furthermore it allows -/// conversion into a iterative solver where each iteration step yields a new eigenvalue/vector -/// pair. -pub struct TruncatedEig { - order: Order, - problem: Array2, - pub constraints: Option>, - preconditioner: Option>, - precision: f32, - maxiter: usize, -} - -impl TruncatedEig { - pub fn new(problem: Array2, order: Order) -> TruncatedEig { - TruncatedEig { - precision: 1e-5, - maxiter: problem.len_of(Axis(0)) * 2, - preconditioner: None, - constraints: None, - order, - problem, - } - } - - pub fn precision(mut self, precision: f32) -> Self { - self.precision = precision; - - self - } - - pub fn maxiter(mut self, maxiter: usize) -> Self { - self.maxiter = maxiter; - - self - } - - pub fn orthogonal_to(mut self, constraints: Array2) -> Self { - self.constraints = Some(constraints); - - self - } - - pub fn precondition_with(mut self, preconditioner: Array2) -> Self { - self.preconditioner = Some(preconditioner); - - self - } - - // calculate the eigenvalues decompose - pub fn decompose(&self, num: usize) -> LobpcgResult { - let x: Array2 = generate::random((self.problem.len_of(Axis(0)), num)); - let x = x.mapv(|x| NumCast::from(x).unwrap()); - - if let Some(ref preconditioner) = self.preconditioner { - lobpcg( - |y| self.problem.dot(&y), - x, - |mut y| { - let p = preconditioner.dot(&y); - y.assign(&p); - }, - self.constraints.clone(), - self.precision, - self.maxiter, - self.order.clone(), - ) - } else { - lobpcg( - |y| self.problem.dot(&y), - x, - |_| {}, - self.constraints.clone(), - self.precision, - self.maxiter, - self.order.clone(), - ) - } - } -} - -impl IntoIterator - for TruncatedEig -{ - type Item = (Array1, Array2); - type IntoIter = TruncatedEigIterator; - - fn into_iter(self) -> TruncatedEigIterator { - TruncatedEigIterator { - step_size: 1, - remaining: self.problem.len_of(Axis(0)), - eig: self, - } - } -} - -/// Truncate eigenproblem iterator -/// -/// This wraps a truncated eigenproblem and provides an iterator where each step yields a new -/// eigenvalue/vector pair. Useful for generating pairs until a certain condition is met. -pub struct TruncatedEigIterator { - step_size: usize, - remaining: usize, - eig: TruncatedEig, -} - -impl Iterator - for TruncatedEigIterator -{ - type Item = (Array1, Array2); - - fn next(&mut self) -> Option { - if self.remaining == 0 { - return None; - } - - let step_size = usize::min(self.step_size, self.remaining); - let res = self.eig.decompose(step_size); - - match res { - LobpcgResult::Ok(vals, vecs, norms) | LobpcgResult::Err(vals, vecs, norms, _) => { - // abort if any eigenproblem did not converge - for r_norm in norms { - if r_norm > NumCast::from(0.1).unwrap() { - return None; - } - } - - // add the new eigenvector to the internal constrain matrix - let new_constraints = if let Some(ref constraints) = self.eig.constraints { - let eigvecs_arr: Vec<_> = constraints - .columns() - .into_iter() - .chain(vecs.columns().into_iter()) - .collect(); - - stack(Axis(1), &eigvecs_arr).unwrap() - } else { - vecs.clone() - }; - - self.eig.constraints = Some(new_constraints); - self.remaining -= step_size; - - Some((vals, vecs)) - } - LobpcgResult::NoResult(_) => None, - } - } -} - -#[cfg(test)] -mod tests { - use super::Order; - use super::TruncatedEig; - use ndarray::{arr1, Array2}; - - #[test] - fn test_truncated_eig() { - let diag = arr1(&[ - 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., - 20., - ]); - let a = Array2::from_diag(&diag); - - let teig = TruncatedEig::new(a, Order::Largest) - .precision(1e-5) - .maxiter(500); - - let res = teig - .into_iter() - .take(3) - .flat_map(|x| x.0.to_vec()) - .collect::>(); - let ground_truth = vec![20., 19., 18.]; - - assert!( - ground_truth - .into_iter() - .zip(res.into_iter()) - .map(|(x, y)| (x - y) * (x - y)) - .sum::() - < 0.01 - ); - } -} diff --git a/ndarray-linalg/src/lobpcg/lobpcg.rs b/ndarray-linalg/src/lobpcg/lobpcg.rs deleted file mode 100644 index 10d12da2..00000000 --- a/ndarray-linalg/src/lobpcg/lobpcg.rs +++ /dev/null @@ -1,617 +0,0 @@ -///! Locally Optimal Block Preconditioned Conjugated -///! -///! This module implements the Locally Optimal Block Preconditioned Conjugated (LOBPCG) algorithm, -///which can be used as a solver for large symmetric positive definite eigenproblems. -use crate::error::{LinalgError, Result}; -use crate::{cholesky::*, close_l2, eigh::*, norm::*, triangular::*}; -use cauchy::Scalar; -use lax::Lapack; -use ndarray::prelude::*; -use ndarray::{Data, OwnedRepr, ScalarOperand}; -use num_traits::{Float, NumCast}; - -/// Find largest or smallest eigenvalues -#[derive(Debug, Clone)] -pub enum Order { - Largest, - Smallest, -} - -/// The result of the eigensolver -/// -/// In the best case the eigensolver has converged with a result better than the given threshold, -/// then a `LobpcgResult::Ok` gives the eigenvalues, eigenvectors and norms. If an error ocurred -/// during the process, it is returned in `LobpcgResult::Err`, but the best result is still returned, -/// as it could be usable. If there is no result at all, then `LobpcgResult::NoResult` is returned. -/// This happens if the algorithm fails in an early stage, for example if the matrix `A` is not SPD -#[derive(Debug)] -pub enum LobpcgResult { - Ok(Array1, Array2, Vec), - Err(Array1, Array2, Vec, LinalgError), - NoResult(LinalgError), -} - -/// Solve full eigenvalue problem, sort by `order` and truncate to `size` -fn sorted_eig, A: Scalar + Lapack>( - a: ArrayBase, - b: Option>, - size: usize, - order: &Order, -) -> Result<(Array1, Array2)> { - let n = a.len_of(Axis(0)); - - let (vals, vecs) = match b { - Some(b) => (a, b).eigh(UPLO::Upper).map(|x| (x.0, (x.1).0))?, - _ => a.eigh(UPLO::Upper)?, - }; - - Ok(match order { - Order::Largest => ( - vals.slice_move(s![n-size..; -1]).mapv(Scalar::from_real), - vecs.slice_move(s![.., n-size..; -1]), - ), - Order::Smallest => ( - vals.slice_move(s![..size]).mapv(Scalar::from_real), - vecs.slice_move(s![.., ..size]), - ), - }) -} - -/// Masks a matrix with the given `matrix` -fn ndarray_mask(matrix: ArrayView2, mask: &[bool]) -> Array2 { - assert_eq!(mask.len(), matrix.ncols()); - - let indices = (0..mask.len()) - .zip(mask.iter()) - .filter(|(_, b)| **b) - .map(|(a, _)| a) - .collect::>(); - - matrix.select(Axis(1), &indices) -} - -/// Applies constraints ensuring that a matrix is orthogonal to it -/// -/// This functions takes a matrix `v` and constraint-matrix `y` and orthogonalize `v` to `y`. -fn apply_constraints( - mut v: ArrayViewMut, - cholesky_yy: &CholeskyFactorized>, - y: ArrayView2, -) { - let gram_yv = y.t().dot(&v); - - let u = gram_yv - .columns() - .into_iter() - .flat_map(|x| { - let res = cholesky_yy.solvec(&x).unwrap(); - - res.to_vec() - }) - .collect::>(); - - let rows = gram_yv.len_of(Axis(0)); - let u = Array2::from_shape_vec((rows, u.len() / rows), u).unwrap(); - - v -= &(y.dot(&u)); -} - -/// Orthonormalize `V` with Cholesky factorization -/// -/// This also returns the matrix `R` of the `QR` problem -fn orthonormalize(v: Array2) -> Result<(Array2, Array2)> { - let gram_vv = v.t().dot(&v); - let gram_vv_fac = gram_vv.cholesky(UPLO::Lower)?; - - close_l2( - &gram_vv, - &gram_vv_fac.dot(&gram_vv_fac.t()), - NumCast::from(1e-5).unwrap(), - ); - - let v_t = v.reversed_axes(); - let u = gram_vv_fac - .solve_triangular(UPLO::Lower, Diag::NonUnit, &v_t)? - .reversed_axes(); - - Ok((u, gram_vv_fac)) -} - -/// Eigenvalue solver for large symmetric positive definite (SPD) eigenproblems -/// -/// # Arguments -/// * `a` - An operator defining the problem, usually a sparse (sometimes also dense) matrix -/// multiplication. Also called the "stiffness matrix". -/// * `x` - Initial approximation of the k eigenvectors. If `a` has shape=(n,n), then `x` should -/// have shape=(n,k). -/// * `m` - Preconditioner to `a`, by default the identity matrix. Should approximate the inverse -/// of `a`. -/// * `y` - Constraints of (n,size_y), iterations are performed in the orthogonal complement of the -/// column-space of `y`. It must be full rank. -/// * `tol` - The tolerance values defines at which point the solver stops the optimization. The approximation -/// of a eigenvalue stops when then l2-norm of the residual is below this threshold. -/// * `maxiter` - The maximal number of iterations -/// * `order` - Whether to solve for the largest or lowest eigenvalues -/// -/// The function returns an `LobpcgResult` with the eigenvalue/eigenvector and achieved residual norm -/// for it. All iterations are tracked and the optimal solution returned. In case of an error a -/// special variant `LobpcgResult::NotConverged` additionally carries the error. This can happen when -/// the precision of the matrix is too low (switch then from `f32` to `f64` for example). -pub fn lobpcg< - A: Float + Scalar + Lapack + ScalarOperand + PartialOrd + Default, - F: Fn(ArrayView2) -> Array2, - G: Fn(ArrayViewMut2), ->( - a: F, - mut x: Array2, - m: G, - y: Option>, - tol: f32, - maxiter: usize, - order: Order, -) -> LobpcgResult { - // the initital approximation should be maximal square - // n is the dimensionality of the problem - let (n, size_x) = (x.nrows(), x.ncols()); - assert!(size_x <= n); - - /*let size_y = match y { - Some(ref y) => y.ncols(), - _ => 0, - }; - - if (n - size_y) < 5 * size_x { - panic!("Please use a different approach, the LOBPCG method only supports the calculation of a couple of eigenvectors!"); - }*/ - - // cap the number of iteration - let mut iter = usize::min(n * 10, maxiter); - let tol = NumCast::from(tol).unwrap(); - - // calculate cholesky factorization of YY' and apply constraints to initial guess - let cholesky_yy = y.as_ref().map(|y| { - let cholesky_yy = y.t().dot(y).factorizec(UPLO::Lower).unwrap(); - apply_constraints(x.view_mut(), &cholesky_yy, y.view()); - cholesky_yy - }); - - // orthonormalize the initial guess - let (x, _) = match orthonormalize(x) { - Ok(x) => x, - Err(err) => return LobpcgResult::NoResult(err), - }; - - // calculate AX and XAX for Rayleigh quotient - let ax = a(x.view()); - let xax = x.t().dot(&ax); - - // perform eigenvalue decomposition of XAX - let (mut lambda, eig_block) = match sorted_eig(xax.view(), None, size_x, &order) { - Ok(x) => x, - Err(err) => return LobpcgResult::NoResult(err), - }; - - // initiate approximation of the eigenvector - let mut x = x.dot(&eig_block); - let mut ax = ax.dot(&eig_block); - - // track residual below threshold - let mut activemask = vec![true; size_x]; - - // track residuals and best result - let mut residual_norms_history = Vec::new(); - let mut best_result = None; - - let mut previous_block_size = size_x; - - let mut ident: Array2 = Array2::eye(size_x); - let ident0: Array2 = Array2::eye(size_x); - let two: A = NumCast::from(2.0).unwrap(); - - let mut previous_p_ap: Option<(Array2, Array2)> = None; - let mut explicit_gram_flag = true; - - let final_norm = loop { - // calculate residual - let lambda_diag = Array2::from_diag(&lambda); - let lambda_x = x.dot(&lambda_diag); - - // calculate residual AX - lambdaX - let r = &ax - &lambda_x; - - // calculate L2 norm of error for every eigenvalue - let residual_norms = r - .columns() - .into_iter() - .map(|x| x.norm()) - .collect::>(); - residual_norms_history.push(residual_norms.clone()); - - // compare best result and update if we improved - let sum_rnorm: A::Real = residual_norms.iter().cloned().sum(); - if best_result - .as_ref() - .map(|x: &(_, _, Vec)| x.2.iter().cloned().sum::() > sum_rnorm) - .unwrap_or(true) - { - best_result = Some((lambda.clone(), x.clone(), residual_norms.clone())); - } - - // disable eigenvalues which are below the tolerance threshold - activemask = residual_norms - .iter() - .zip(activemask.iter()) - .map(|(x, a)| *x > tol && *a) - .collect(); - - // resize identity block if necessary - let current_block_size = activemask.iter().filter(|x| **x).count(); - if current_block_size != previous_block_size { - previous_block_size = current_block_size; - ident = Array2::eye(current_block_size); - } - - // if we are below the threshold for all eigenvalue or exceeded the number of iteration, - // abort - if current_block_size == 0 || iter == 0 { - break Ok(residual_norms); - } - - // select active eigenvalues, apply pre-conditioner, orthogonalize to Y and orthonormalize - let mut active_block_r = ndarray_mask(r.view(), &activemask); - // apply preconditioner - m(active_block_r.view_mut()); - // apply constraints to the preconditioned residuals - if let (Some(ref y), Some(ref cholesky_yy)) = (&y, &cholesky_yy) { - apply_constraints(active_block_r.view_mut(), cholesky_yy, y.view()); - } - // orthogonalize the preconditioned residual to x - active_block_r -= &x.dot(&x.t().dot(&active_block_r)); - - let (r, _) = match orthonormalize(active_block_r) { - Ok(x) => x, - Err(err) => break Err(err), - }; - - let ar = a(r.view()); - - // check whether `A` is of type `f32` or `f64` - let max_rnorm_float = if A::epsilon() > NumCast::from(1e-8).unwrap() { - NumCast::from(1.0).unwrap() - } else { - NumCast::from(1.0e-8).unwrap() - }; - - // if we are once below the max_rnorm, enable explicit gram flag - let max_norm = residual_norms - .into_iter() - .fold(A::Real::neg_infinity(), A::Real::max); - explicit_gram_flag = max_norm <= max_rnorm_float || explicit_gram_flag; - - // perform the Rayleigh Ritz procedure - let xar = x.t().dot(&ar); - let mut rar = r.t().dot(&ar); - - // for small residuals calculate covariance matrices explicitely, otherwise approximate - // them such that X is orthogonal and uncorrelated to the residual R and use eigenvalues of - // previous decomposition - let (xax, xx, rr, xr) = if explicit_gram_flag { - rar = (&rar + &rar.t()) / two; - let xax = x.t().dot(&ax); - - ( - (&xax + &xax.t()) / two, - x.t().dot(&x), - r.t().dot(&r), - x.t().dot(&r), - ) - } else { - ( - lambda_diag, - ident0.clone(), - ident.clone(), - Array2::zeros((size_x, current_block_size)), - ) - }; - - // mask and orthonormalize P and AP - let mut p_ap = previous_p_ap - .as_ref() - .and_then(|(p, ap)| { - let active_p = ndarray_mask(p.view(), &activemask); - let active_ap = ndarray_mask(ap.view(), &activemask); - - orthonormalize(active_p).map(|x| (active_ap, x)).ok() - }) - .and_then(|(active_ap, (active_p, p_r))| { - // orthonormalize AP with R^{-1} of A - let active_ap = active_ap.reversed_axes(); - p_r.solve_triangular(UPLO::Lower, Diag::NonUnit, &active_ap) - .map(|active_ap| (active_p, active_ap.reversed_axes())) - .ok() - }); - - // compute symmetric gram matrices and calculate solution of eigenproblem - // - // first try to compute the eigenvalue decomposition of the span{R, X, P}, - // if this fails (or the algorithm was restarted), then just use span{R, X} - let result = p_ap - .as_ref() - .ok_or(LinalgError::Lapack( - lax::error::Error::LapackComputationalFailure { return_code: 1 }, - )) - .and_then(|(active_p, active_ap)| { - let xap = x.t().dot(active_ap); - let rap = r.t().dot(active_ap); - let pap = active_p.t().dot(active_ap); - let xp = x.t().dot(active_p); - let rp = r.t().dot(active_p); - let (pap, pp) = if explicit_gram_flag { - ((&pap + &pap.t()) / two, active_p.t().dot(active_p)) - } else { - (pap, ident.clone()) - }; - - sorted_eig( - concatenate![ - Axis(0), - concatenate![Axis(1), xax, xar, xap], - concatenate![Axis(1), xar.t(), rar, rap], - concatenate![Axis(1), xap.t(), rap.t(), pap] - ], - Some(concatenate![ - Axis(0), - concatenate![Axis(1), xx, xr, xp], - concatenate![Axis(1), xr.t(), rr, rp], - concatenate![Axis(1), xp.t(), rp.t(), pp] - ]), - size_x, - &order, - ) - }) - .or_else(|_| { - p_ap = None; - - sorted_eig( - concatenate![ - Axis(0), - concatenate![Axis(1), xax, xar], - concatenate![Axis(1), xar.t(), rar] - ], - Some(concatenate![ - Axis(0), - concatenate![Axis(1), xx, xr], - concatenate![Axis(1), xr.t(), rr] - ]), - size_x, - &order, - ) - }); - - // update eigenvalues and eigenvectors (lambda is also used in the next iteration) - let eig_vecs; - match result { - Ok((x, y)) => { - lambda = x; - eig_vecs = y; - } - Err(x) => break Err(x), - } - - // approximate eigenvector X and conjugate vectors P with solution of eigenproblem - let (p, ap, tau) = if let Some((active_p, active_ap)) = p_ap { - // tau are eigenvalues to basis of X - let tau = eig_vecs.slice(s![..size_x, ..]); - // alpha are eigenvalues to basis of R - let alpha = eig_vecs.slice(s![size_x..size_x + current_block_size, ..]); - // gamma are eigenvalues to basis of P - let gamma = eig_vecs.slice(s![size_x + current_block_size.., ..]); - - // update AP and P in span{R, P} as linear combination - let updated_p = r.dot(&alpha) + active_p.dot(&gamma); - let updated_ap = ar.dot(&alpha) + active_ap.dot(&gamma); - - (updated_p, updated_ap, tau) - } else { - // tau are eigenvalues to basis of X - let tau = eig_vecs.slice(s![..size_x, ..]); - // alpha are eigenvalues to basis of R - let alpha = eig_vecs.slice(s![size_x.., ..]); - - // update AP and P as linear combination of the residual matrix R - let updated_p = r.dot(&alpha); - let updated_ap = ar.dot(&alpha); - - (updated_p, updated_ap, tau) - }; - - // update approximation of X as linear combinations of span{X, P, R} - x = x.dot(&tau) + &p; - ax = ax.dot(&tau) + ≈ - - previous_p_ap = Some((p, ap)); - - iter -= 1; - }; - - // retrieve best result and convert norm into `A` - let (vals, vecs, rnorm) = best_result.unwrap(); - let rnorm = rnorm.into_iter().map(Scalar::from_real).collect(); - - match final_norm { - Ok(_) => LobpcgResult::Ok(vals, vecs, rnorm), - Err(err) => LobpcgResult::Err(vals, vecs, rnorm, err), - } -} - -#[cfg(test)] -mod tests { - use super::lobpcg; - use super::ndarray_mask; - use super::orthonormalize; - use super::sorted_eig; - use super::LobpcgResult; - use super::Order; - use crate::close_l2; - use crate::generate; - use crate::qr::*; - use ndarray::prelude::*; - - /// Test the `sorted_eigen` function - #[test] - fn test_sorted_eigen() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let matrix: Array2 = generate::random_using((10, 10), &mut rng) * 10.0; - let matrix = matrix.t().dot(&matrix); - - // return all eigenvectors with largest first - let (vals, vecs) = sorted_eig(matrix.view(), None, 10, &Order::Largest).unwrap(); - - // calculate V * A * V' and compare to original matrix - let diag = Array2::from_diag(&vals); - let rec = (vecs.dot(&diag)).dot(&vecs.t()); - - close_l2(&matrix, &rec, 1e-5); - } - - /// Test the masking function - #[test] - fn test_masking() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let matrix: Array2 = generate::random_using((10, 5), &mut rng) * 10.0; - let masked_matrix = ndarray_mask(matrix.view(), &[true, true, false, true, false]); - close_l2( - &masked_matrix.slice(s![.., 2]), - &matrix.slice(s![.., 3]), - 1e-12, - ); - } - - /// Test orthonormalization of a random matrix - #[test] - fn test_orthonormalize() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let matrix: Array2 = generate::random_using((10, 10), &mut rng) * 10.0; - - let (n, l) = orthonormalize(matrix.clone()).unwrap(); - - // check for orthogonality - let identity = n.dot(&n.t()); - close_l2(&identity, &Array2::eye(10), 1e-2); - - // compare returned factorization with QR decomposition - let (_, r) = matrix.qr().unwrap(); - close_l2(&r.mapv(|x| x.abs()), &l.t().mapv(|x| x.abs()), 1e-2); - } - - fn assert_symmetric(a: &Array2) { - close_l2(a, &a.t(), 1e-5); - } - - fn check_eigenvalues(a: &Array2, order: Order, num: usize, ground_truth_eigvals: &[f64]) { - assert_symmetric(a); - - let n = a.len_of(Axis(0)); - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let x: Array2 = generate::random_using((n, num), &mut rng); - - let result = lobpcg(|y| a.dot(&y), x, |_| {}, None, 1e-5, n * 2, order); - match result { - LobpcgResult::Ok(vals, _, r_norms) | LobpcgResult::Err(vals, _, r_norms, _) => { - // check convergence - for (i, norm) in r_norms.into_iter().enumerate() { - if norm > 1e-5 { - println!("==== Assertion Failed ===="); - println!("The {}th eigenvalue estimation did not converge!", i); - panic!("Too large deviation of residual norm: {} > 0.01", norm); - } - } - - // check correct order of eigenvalues - if ground_truth_eigvals.len() == num { - close_l2( - &Array1::from(ground_truth_eigvals.to_vec()), - &vals, - num as f64 * 5e-4, - ) - } - } - LobpcgResult::NoResult(err) => panic!("Did not converge: {:?}", err), - } - } - - /// Test the eigensolver with a identity matrix problem and a random initial solution - #[test] - fn test_eigsolver_diag() { - let diag = arr1(&[ - 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., - 20., - ]); - let a = Array2::from_diag(&diag); - - check_eigenvalues(&a, Order::Largest, 3, &[20., 19., 18.]); - check_eigenvalues(&a, Order::Smallest, 3, &[1., 2., 3.]); - } - - /// Test the eigensolver with matrix of constructed eigenvalues - #[test] - fn test_eigsolver_constructed() { - let n = 50; - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let tmp = generate::random_using((n, n), &mut rng); - //let (v, _) = tmp.qr_square().unwrap(); - let (v, _) = orthonormalize(tmp).unwrap(); - - // set eigenvalues in decreasing order - let t = Array2::from_diag(&Array1::linspace(n as f64, -(n as f64), n)); - let a = v.dot(&t.dot(&v.t())); - - // find five largest eigenvalues - check_eigenvalues(&a, Order::Largest, 5, &[50.0, 48.0, 46.0, 44.0, 42.0]); - check_eigenvalues(&a, Order::Smallest, 5, &[-50.0, -48.0, -46.0, -44.0, -42.0]); - } - - #[test] - fn test_eigsolver_constrained() { - let diag = arr1(&[1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]); - let a = Array2::from_diag(&diag); - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let x: Array2 = generate::random_using((10, 1), &mut rng); - let y: Array2 = arr2(&[ - [1.0, 0., 0., 0., 0., 0., 0., 0., 0., 0.], - [0., 1.0, 0., 0., 0., 0., 0., 0., 0., 0.], - ]) - .reversed_axes(); - - let result = lobpcg( - |y| a.dot(&y), - x, - |_| {}, - Some(y), - 1e-10, - 50, - Order::Smallest, - ); - match result { - LobpcgResult::Ok(vals, vecs, r_norms) | LobpcgResult::Err(vals, vecs, r_norms, _) => { - // check convergence - for (i, norm) in r_norms.into_iter().enumerate() { - if norm > 0.01 { - println!("==== Assertion Failed ===="); - println!("The {}th eigenvalue estimation did not converge!", i); - panic!("Too large deviation of residual norm: {} > 0.01", norm); - } - } - - // should be the third eigenvalue - close_l2(&vals, &Array1::from(vec![3.0]), 1e-10); - close_l2( - &vecs.column(0).mapv(|x| x.abs()), - &arr1(&[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), - 1e-5, - ); - } - LobpcgResult::NoResult(err) => panic!("Did not converge: {:?}", err), - } - } -} diff --git a/ndarray-linalg/src/lobpcg/mod.rs b/ndarray-linalg/src/lobpcg/mod.rs deleted file mode 100644 index 0c0bce47..00000000 --- a/ndarray-linalg/src/lobpcg/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod eig; -mod lobpcg; -mod svd; - -pub use eig::TruncatedEig; -pub use lobpcg::{lobpcg, LobpcgResult, Order as TruncatedOrder}; -pub use svd::TruncatedSvd; diff --git a/ndarray-linalg/src/lobpcg/svd.rs b/ndarray-linalg/src/lobpcg/svd.rs deleted file mode 100644 index 62d18b49..00000000 --- a/ndarray-linalg/src/lobpcg/svd.rs +++ /dev/null @@ -1,231 +0,0 @@ -///! Truncated singular value decomposition -///! -///! This module computes the k largest/smallest singular values/vectors for a dense matrix. -use super::lobpcg::{lobpcg, LobpcgResult, Order}; -use crate::error::Result; -use crate::generate; -use cauchy::Scalar; -use lax::Lapack; -use ndarray::prelude::*; -use ndarray::ScalarOperand; -use num_traits::{Float, NumCast}; -use std::ops::DivAssign; - -/// The result of a eigenvalue decomposition, not yet transformed into singular values/vectors -/// -/// Provides methods for either calculating just the singular values with reduced cost or the -/// vectors with additional cost of matrix multiplication. -#[derive(Debug)] -pub struct TruncatedSvdResult { - eigvals: Array1, - eigvecs: Array2, - problem: Array2, - ngm: bool, -} - -impl + 'static + MagnitudeCorrection> TruncatedSvdResult { - /// Returns singular values ordered by magnitude with indices. - fn singular_values_with_indices(&self) -> (Array1, Vec) { - // numerate eigenvalues - let mut a = self.eigvals.iter().enumerate().collect::>(); - - // sort by magnitude - a.sort_by(|(_, x), (_, y)| x.partial_cmp(y).unwrap().reverse()); - - // calculate cut-off magnitude (borrowed from scipy) - let cutoff = A::epsilon() * // float precision - A::correction() * // correction term (see trait below) - *a[0].1; // max eigenvalue - - // filter low singular values away - let (values, indices): (Vec, Vec) = a - .into_iter() - .filter(|(_, x)| *x > &cutoff) - .map(|(a, b)| (b.sqrt(), a)) - .unzip(); - - (Array1::from(values), indices) - } - - /// Returns singular values ordered by magnitude - pub fn values(&self) -> Array1 { - let (values, _) = self.singular_values_with_indices(); - - values - } - - /// Returns singular values, left-singular vectors and right-singular vectors - pub fn values_vectors(&self) -> (Array2, Array1, Array2) { - let (values, indices) = self.singular_values_with_indices(); - - // branch n > m (for A is [n x m]) - let (u, v) = if self.ngm { - let vlarge = self.eigvecs.select(Axis(1), &indices); - let mut ularge = self.problem.dot(&vlarge); - - ularge - .columns_mut() - .into_iter() - .zip(values.iter()) - .for_each(|(mut a, b)| a.mapv_inplace(|x| x / *b)); - - (ularge, vlarge) - } else { - let ularge = self.eigvecs.select(Axis(1), &indices); - - let mut vlarge = self.problem.t().dot(&ularge); - vlarge - .columns_mut() - .into_iter() - .zip(values.iter()) - .for_each(|(mut a, b)| a.mapv_inplace(|x| x / *b)); - - (ularge, vlarge) - }; - - (u, values, v.reversed_axes()) - } -} - -/// Truncated singular value decomposition -/// -/// Wraps the LOBPCG algorithm and provides convenient builder-pattern access to -/// parameter like maximal iteration, precision and constraint matrix. -pub struct TruncatedSvd { - order: Order, - problem: Array2, - precision: f32, - maxiter: usize, -} - -impl TruncatedSvd { - pub fn new(problem: Array2, order: Order) -> TruncatedSvd { - TruncatedSvd { - precision: 1e-5, - maxiter: problem.len_of(Axis(0)) * 2, - order, - problem, - } - } - - pub fn precision(mut self, precision: f32) -> Self { - self.precision = precision; - - self - } - - pub fn maxiter(mut self, maxiter: usize) -> Self { - self.maxiter = maxiter; - - self - } - - // calculate the eigenvalue decomposition - pub fn decompose(self, num: usize) -> Result> { - if num < 1 { - panic!("The number of singular values to compute should be larger than zero!"); - } - - let (n, m) = (self.problem.nrows(), self.problem.ncols()); - - // generate initial matrix - let x: Array2 = generate::random((usize::min(n, m), num)); - let x = x.mapv(|x| NumCast::from(x).unwrap()); - - // square precision because the SVD squares the eigenvalue as well - let precision = self.precision * self.precision; - - // use problem definition with less operations required - let res = if n > m { - lobpcg( - |y| self.problem.t().dot(&self.problem.dot(&y)), - x, - |_| {}, - None, - precision, - self.maxiter, - self.order.clone(), - ) - } else { - lobpcg( - |y| self.problem.dot(&self.problem.t().dot(&y)), - x, - |_| {}, - None, - precision, - self.maxiter, - self.order.clone(), - ) - }; - - // convert into TruncatedSvdResult - match res { - LobpcgResult::Ok(vals, vecs, _) | LobpcgResult::Err(vals, vecs, _, _) => { - Ok(TruncatedSvdResult { - problem: self.problem, - eigvals: vals, - eigvecs: vecs, - ngm: n > m, - }) - } - LobpcgResult::NoResult(err) => Err(err), - } - } -} - -pub trait MagnitudeCorrection { - fn correction() -> Self; -} - -impl MagnitudeCorrection for f32 { - fn correction() -> Self { - 1.0e3 - } -} - -impl MagnitudeCorrection for f64 { - fn correction() -> Self { - 1.0e6 - } -} - -#[cfg(test)] -mod tests { - use super::Order; - use super::TruncatedSvd; - use crate::{close_l2, generate}; - - use ndarray::{arr1, arr2, Array2}; - - #[test] - fn test_truncated_svd() { - let a = arr2(&[[3., 2., 2.], [2., 3., -2.]]); - - let res = TruncatedSvd::new(a, Order::Largest) - .precision(1e-5) - .maxiter(10) - .decompose(2) - .unwrap(); - - let (_, sigma, _) = res.values_vectors(); - - close_l2(&sigma, &arr1(&[5.0, 3.0]), 1e-5); - } - - #[test] - fn test_truncated_svd_random() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = generate::random_using((50, 10), &mut rng); - - let res = TruncatedSvd::new(a.clone(), Order::Largest) - .precision(1e-5) - .maxiter(10) - .decompose(10) - .unwrap(); - - let (u, sigma, v_t) = res.values_vectors(); - let reconstructed = u.dot(&Array2::from_diag(&sigma).dot(&v_t)); - - close_l2(&a, &reconstructed, 1e-5); - } -} diff --git a/ndarray-linalg/src/norm.rs b/ndarray-linalg/src/norm.rs deleted file mode 100644 index e0dde1a4..00000000 --- a/ndarray-linalg/src/norm.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! Norm of vectors - -use ndarray::*; -use num_traits::Zero; - -use super::types::*; - -/// Define norm as a metric linear space (not as a matrix) -/// -/// For operator norms, see opnorm module -pub trait Norm { - type Output; - /// rename of `norm_l2` - fn norm(&self) -> Self::Output { - self.norm_l2() - } - /// L-1 norm - fn norm_l1(&self) -> Self::Output; - /// L-2 norm - fn norm_l2(&self) -> Self::Output; - /// maximum norm - fn norm_max(&self) -> Self::Output; -} - -impl Norm for ArrayBase -where - A: Scalar + Lapack, - S: Data, - D: Dimension, -{ - type Output = A::Real; - fn norm_l1(&self) -> Self::Output { - self.iter().map(|x| x.abs()).sum() - } - fn norm_l2(&self) -> Self::Output { - self.iter().map(|x| x.square()).sum::().sqrt() - } - fn norm_max(&self) -> Self::Output { - self.iter().fold(A::Real::zero(), |f, &val| { - let v = val.abs(); - if f > v { - f - } else { - v - } - }) - } -} - -pub enum NormalizeAxis { - Row = 0, - Column = 1, -} - -/// normalize in L2 norm -pub fn normalize( - mut m: ArrayBase, - axis: NormalizeAxis, -) -> (ArrayBase, Vec) -where - A: Scalar + Lapack, - S: DataMut, -{ - let mut ms = Vec::new(); - for mut v in m.axis_iter_mut(Axis(axis as usize)) { - let n = v.norm(); - ms.push(n); - v.map_inplace(|x| *x /= A::from_real(n)) - } - (m, ms) -} diff --git a/ndarray-linalg/src/operator.rs b/ndarray-linalg/src/operator.rs deleted file mode 100644 index 368650bf..00000000 --- a/ndarray-linalg/src/operator.rs +++ /dev/null @@ -1,82 +0,0 @@ -//! Linear operator algebra - -use crate::generate::hstack; -use crate::types::*; -use ndarray::*; - -/// Abstracted linear operator as an action to vector (`ArrayBase`) and matrix -/// (`ArrayBase(&self, a: &ArrayBase) -> Array1 - where - S: Data, - { - let mut a = a.to_owned(); - self.apply_mut(&mut a); - a - } - - /// Apply operator in-place - fn apply_mut(&self, a: &mut ArrayBase) - where - S: DataMut, - { - let b = self.apply(a); - azip!((a in a, &b in &b) *a = b); - } - - /// Apply operator with move - fn apply_into(&self, mut a: ArrayBase) -> ArrayBase - where - S: DataOwned + DataMut, - { - self.apply_mut(&mut a); - a - } - - /// Apply operator to matrix out-place - fn apply2(&self, a: &ArrayBase) -> Array2 - where - S: Data, - { - let cols: Vec<_> = a.axis_iter(Axis(1)).map(|col| self.apply(&col)).collect(); - hstack(&cols).unwrap() - } - - /// Apply operator to matrix in-place - fn apply2_mut(&self, a: &mut ArrayBase) - where - S: DataMut, - { - for mut col in a.axis_iter_mut(Axis(1)) { - self.apply_mut(&mut col) - } - } - - /// Apply operator to matrix with move - fn apply2_into(&self, mut a: ArrayBase) -> ArrayBase - where - S: DataOwned + DataMut, - { - self.apply2_mut(&mut a); - a - } -} - -impl LinearOperator for ArrayBase -where - A: Scalar, - Sa: Data, -{ - type Elem = A; - - fn apply(&self, a: &ArrayBase) -> Array1 - where - S: Data, - { - self.dot(a) - } -} diff --git a/ndarray-linalg/src/opnorm.rs b/ndarray-linalg/src/opnorm.rs deleted file mode 100644 index 0a412580..00000000 --- a/ndarray-linalg/src/opnorm.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! Operator norm - -use lax::Tridiagonal; -use ndarray::*; - -use crate::error::*; -use crate::layout::*; -use crate::types::*; - -pub use lax::NormType; - -/// Operator norm using `*lange` LAPACK routines -/// -/// [Wikipedia article on operator norm](https://en.wikipedia.org/wiki/Operator_norm) -pub trait OperationNorm { - /// the value of norm - type Output: Scalar; - - fn opnorm(&self, t: NormType) -> Result; - - /// the one norm of a matrix (maximum column sum) - fn opnorm_one(&self) -> Result { - self.opnorm(NormType::One) - } - - /// the infinity norm of a matrix (maximum row sum) - fn opnorm_inf(&self) -> Result { - self.opnorm(NormType::Infinity) - } - - /// the Frobenius norm of a matrix (square root of sum of squares) - fn opnorm_fro(&self) -> Result { - self.opnorm(NormType::Frobenius) - } -} - -impl OperationNorm for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type Output = A::Real; - - fn opnorm(&self, t: NormType) -> Result { - let l = self.layout()?; - let a = self.as_allocated()?; - Ok(A::opnorm(t, l, a)) - } -} - -impl OperationNorm for Tridiagonal -where - A: Scalar + Lapack, -{ - type Output = A::Real; - - fn opnorm(&self, t: NormType) -> Result { - // `self` is a tridiagonal matrix like, - // [d0, u1, 0, ..., 0, - // l1, d1, u2, ..., - // 0, l2, d2, - // ... ..., u{n-1}, - // 0, ..., l{n-1}, d{n-1},] - let arr = match t { - // opnorm_one() calculates muximum column sum. - // Therefore, This part align the columns and make a (3 x n) matrix like, - // [ 0, u1, u2, ..., u{n-1}, - // d0, d1, d2, ..., d{n-1}, - // l1, l2, l3, ..., 0,] - NormType::One => { - let zl: Array1 = Array::zeros(1); - let zu: Array1 = Array::zeros(1); - let dl = concatenate![Axis(0), &self.dl, zl]; // n - let du = concatenate![Axis(0), zu, &self.du]; // n - stack![Axis(0), du, &self.d, dl] // 3 x n - } - // opnorm_inf() calculates muximum row sum. - // Therefore, This part align the rows and make a (n x 3) matrix like, - // [ 0, d0, u1, - // l1, d1, u2, - // l2, d2, u3, - // ..., ..., ..., - // l{n-1}, d{n-1}, 0,] - NormType::Infinity => { - let zl: Array1 = Array::zeros(1); - let zu: Array1 = Array::zeros(1); - let dl = concatenate![Axis(0), zl, &self.dl]; // n - let du = concatenate![Axis(0), &self.du, zu]; // n - stack![Axis(1), dl, &self.d, du] // n x 3 - } - // opnorm_fro() calculates square root of sum of squares. - // Because it is independent of the shape of matrix, - // this part make a (1 x (3n-2)) matrix like, - // [l1, ..., l{n-1}, d0, ..., d{n-1}, u1, ..., u{n-1}] - NormType::Frobenius => { - concatenate![Axis(0), &self.dl, &self.d, &self.du].insert_axis(Axis(0)) - } - }; - let l = arr.layout()?; - let a = arr.as_allocated()?; - Ok(A::opnorm(t, l, a)) - } -} diff --git a/ndarray-linalg/src/qr.rs b/ndarray-linalg/src/qr.rs deleted file mode 100644 index 4bf2f0ec..00000000 --- a/ndarray-linalg/src/qr.rs +++ /dev/null @@ -1,155 +0,0 @@ -//! QR decomposition -//! -//! [Wikipedia article on QR decomposition](https://en.wikipedia.org/wiki/QR_decomposition) - -use ndarray::*; -use num_traits::Zero; - -use crate::convert::*; -use crate::error::*; -use crate::layout::*; -use crate::triangular::*; -use crate::types::*; - -pub use lax::UPLO; - -/// QR decomposition for matrix reference -/// -/// This creates copy due for reshaping array. -/// To avoid copy and the matrix is square, please use `QRSquare*` traits. -pub trait QR { - type Q; - type R; - fn qr(&self) -> Result<(Self::Q, Self::R)>; -} - -/// QR decomposition -/// -/// This creates copy due for reshaping array. -/// To avoid copy and the matrix is square, please use `QRSquare*` traits. -pub trait QRInto: Sized { - type Q; - type R; - fn qr_into(self) -> Result<(Self::Q, Self::R)>; -} - -/// QR decomposition for square matrix reference -pub trait QRSquare: Sized { - type Q; - type R; - fn qr_square(&self) -> Result<(Self::Q, Self::R)>; -} - -/// QR decomposition for square matrix -pub trait QRSquareInto: Sized { - type R; - fn qr_square_into(self) -> Result<(Self, Self::R)>; -} - -/// QR decomposition for mutable reference of square matrix -pub trait QRSquareInplace: Sized { - type R; - fn qr_square_inplace(&mut self) -> Result<(&mut Self, Self::R)>; -} - -impl QRSquareInplace for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type R = Array2; - - fn qr_square_inplace(&mut self) -> Result<(&mut Self, Self::R)> { - let l = self.square_layout()?; - let r = A::qr(l, self.as_allocated_mut()?)?; - let r: Array2<_> = into_matrix(l, r)?; - Ok((self, r.into_triangular(UPLO::Upper))) - } -} - -impl QRSquareInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type R = Array2; - - fn qr_square_into(mut self) -> Result<(Self, Self::R)> { - let (_, r) = self.qr_square_inplace()?; - Ok((self, r)) - } -} - -impl QRSquare for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type Q = Array2; - type R = Array2; - - fn qr_square(&self) -> Result<(Self::Q, Self::R)> { - let a = self.to_owned(); - a.qr_square_into() - } -} - -impl QRInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type Q = Array2; - type R = Array2; - - fn qr_into(mut self) -> Result<(Self::Q, Self::R)> { - let n = self.nrows(); - let m = self.ncols(); - let k = ::std::cmp::min(n, m); - let l = self.layout()?; - let r = A::qr(l, self.as_allocated_mut()?)?; - let r: Array2<_> = into_matrix(l, r)?; - let q = self; - Ok((take_slice(&q, n, k), take_slice_upper(&r, k, m))) - } -} - -impl QR for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type Q = Array2; - type R = Array2; - - fn qr(&self) -> Result<(Self::Q, Self::R)> { - let a = self.to_owned(); - a.qr_into() - } -} - -fn take_slice(a: &ArrayBase, n: usize, m: usize) -> ArrayBase -where - A: Copy, - S1: Data, - S2: DataMut + DataOwned, -{ - let av = a.slice(s![..n as isize, ..m as isize]); - replicate(&av) -} - -fn take_slice_upper(a: &ArrayBase, n: usize, m: usize) -> ArrayBase -where - A: Copy + Zero, - S1: Data, - S2: DataMut + DataOwned, -{ - let av = a.slice(s![..n, ..m]); - let mut a = replicate(&av); - Zip::indexed(&mut a).for_each(|(i, j), elt| { - if i > j { - *elt = A::zero() - } - }); - a -} diff --git a/ndarray-linalg/src/solve.rs b/ndarray-linalg/src/solve.rs deleted file mode 100644 index 79df1f77..00000000 --- a/ndarray-linalg/src/solve.rs +++ /dev/null @@ -1,633 +0,0 @@ -//! Solve systems of linear equations and invert matrices -//! -//! # Examples -//! -//! Solve `A * x = b`: -//! -//! ``` -//! use ndarray::prelude::*; -//! use ndarray_linalg::Solve; -//! -//! let a: Array2 = array![[3., 2., -1.], [2., -2., 4.], [-2., 1., -2.]]; -//! let b: Array1 = array![1., -2., 0.]; -//! let x = a.solve_into(b).unwrap(); -//! assert!(x.abs_diff_eq(&array![1., -2., -2.], 1e-9)); -//! ``` -//! -//! There are also special functions for solving `A^T * x = b` and -//! `A^H * x = b`. -//! -//! If you are solving multiple systems of linear equations with the same -//! coefficient matrix `A`, it's faster to compute the LU factorization once at -//! the beginning than solving directly using `A`: -//! -//! ``` -//! use ndarray::prelude::*; -//! use ndarray_linalg::*; -//! -//! /// Use fixed algorithm and seed of PRNG for reproducible test -//! let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); -//! -//! let a: Array2 = random_using((3, 3), &mut rng); -//! let f = a.factorize_into().unwrap(); // LU factorize A (A is consumed) -//! for _ in 0..10 { -//! let b: Array1 = random_using(3, &mut rng); -//! let x = f.solve_into(b).unwrap(); // Solve A * x = b using factorized L, U -//! } -//! ``` - -use ndarray::*; -use num_traits::{Float, Zero}; - -use crate::convert::*; -use crate::error::*; -use crate::layout::*; -use crate::opnorm::OperationNorm; -use crate::types::*; - -pub use lax::{Pivot, Transpose}; - -/// An interface for solving systems of linear equations. -/// -/// There are three groups of methods: -/// -/// * `solve*` (normal) methods solve `A * x = b` for `x`. -/// * `solve_t*` (transpose) methods solve `A^T * x = b` for `x`. -/// * `solve_h*` (Hermitian conjugate) methods solve `A^H * x = b` for `x`. -/// -/// Within each group, there are three methods that handle ownership differently: -/// -/// * `*` methods take a reference to `b` and return `x` as a new array. -/// * `*_into` methods take ownership of `b`, store the result in it, and return it. -/// * `*_inplace` methods take a mutable reference to `b` and store the result in that array. -/// -/// If you plan to solve many equations with the same `A` matrix but different -/// `b` vectors, it's faster to factor the `A` matrix once using the -/// `Factorize` trait, and then solve using the `LUFactorized` struct. -pub trait Solve { - /// Solves a system of linear equations `A * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of columns - /// of `A`. - fn solve>(&self, b: &ArrayBase) -> Result> { - let mut b = replicate(b); - self.solve_inplace(&mut b)?; - Ok(b) - } - - /// Solves a system of linear equations `A * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of columns - /// of `A`. - fn solve_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_inplace(&mut b)?; - Ok(b) - } - - /// Solves a system of linear equations `A * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of columns - /// of `A`. - fn solve_inplace<'a, S: DataMut>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; - - /// Solves a system of linear equations `A^T * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of rows of - /// `A`. - fn solve_t>(&self, b: &ArrayBase) -> Result> { - let mut b = replicate(b); - self.solve_t_inplace(&mut b)?; - Ok(b) - } - - /// Solves a system of linear equations `A^T * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of rows of - /// `A`. - fn solve_t_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_t_inplace(&mut b)?; - Ok(b) - } - - /// Solves a system of linear equations `A^T * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of rows of - /// `A`. - fn solve_t_inplace<'a, S: DataMut>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; - - /// Solves a system of linear equations `A^H * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of rows of - /// `A`. - fn solve_h>(&self, b: &ArrayBase) -> Result> { - let mut b = replicate(b); - self.solve_h_inplace(&mut b)?; - Ok(b) - } - /// Solves a system of linear equations `A^H * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of rows of - /// `A`. - fn solve_h_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_h_inplace(&mut b)?; - Ok(b) - } - /// Solves a system of linear equations `A^H * x = b` where `A` is `self`, `b` - /// is the argument, and `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of rows of - /// `A`. - fn solve_h_inplace<'a, S: DataMut>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; -} - -/// Represents the LU factorization of a matrix `A` as `A = P*L*U`. -#[derive(Clone)] -pub struct LUFactorized { - /// The factors `L` and `U`; the unit diagonal elements of `L` are not - /// stored. - a: ArrayBase, - /// The pivot indices that define the permutation matrix `P`. - ipiv: Pivot, -} - -impl Solve for LUFactorized -where - A: Scalar + Lapack, - S: Data + RawDataClone, -{ - fn solve_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - assert_eq!( - rhs.len(), - self.a.len_of(Axis(1)), - "The length of `rhs` must be compatible with the shape of the factored matrix.", - ); - A::solve( - self.a.square_layout()?, - Transpose::No, - self.a.as_allocated()?, - &self.ipiv, - rhs.as_slice_mut().unwrap(), - )?; - Ok(rhs) - } - fn solve_t_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - assert_eq!( - rhs.len(), - self.a.len_of(Axis(0)), - "The length of `rhs` must be compatible with the shape of the factored matrix.", - ); - A::solve( - self.a.square_layout()?, - Transpose::Transpose, - self.a.as_allocated()?, - &self.ipiv, - rhs.as_slice_mut().unwrap(), - )?; - Ok(rhs) - } - fn solve_h_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - assert_eq!( - rhs.len(), - self.a.len_of(Axis(0)), - "The length of `rhs` must be compatible with the shape of the factored matrix.", - ); - A::solve( - self.a.square_layout()?, - Transpose::Hermite, - self.a.as_allocated()?, - &self.ipiv, - rhs.as_slice_mut().unwrap(), - )?; - Ok(rhs) - } -} - -impl Solve for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn solve_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize()?; - f.solve_inplace(rhs) - } - fn solve_t_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize()?; - f.solve_t_inplace(rhs) - } - fn solve_h_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize()?; - f.solve_h_inplace(rhs) - } -} - -/// An interface for computing LU factorizations of matrix refs. -pub trait Factorize { - /// Computes the LU factorization `A = P*L*U`, where `P` is a permutation - /// matrix. - fn factorize(&self) -> Result>; -} - -/// An interface for computing LU factorizations of matrices. -pub trait FactorizeInto { - /// Computes the LU factorization `A = P*L*U`, where `P` is a permutation - /// matrix. - fn factorize_into(self) -> Result>; -} - -impl FactorizeInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut + RawDataClone, -{ - fn factorize_into(mut self) -> Result> { - let ipiv = A::lu(self.layout()?, self.as_allocated_mut()?)?; - Ok(LUFactorized { a: self, ipiv }) - } -} - -impl Factorize> for ArrayBase -where - A: Scalar + Lapack, - Si: Data, -{ - fn factorize(&self) -> Result>> { - let mut a: Array2 = replicate(self); - let ipiv = A::lu(a.layout()?, a.as_allocated_mut()?)?; - Ok(LUFactorized { a, ipiv }) - } -} - -/// An interface for inverting matrix refs. -pub trait Inverse { - type Output; - /// Computes the inverse of the matrix. - fn inv(&self) -> Result; -} - -/// An interface for inverting matrices. -pub trait InverseInto { - type Output; - /// Computes the inverse of the matrix. - fn inv_into(self) -> Result; -} - -impl InverseInto for LUFactorized -where - A: Scalar + Lapack, - S: DataMut + RawDataClone, -{ - type Output = ArrayBase; - - fn inv_into(mut self) -> Result> { - A::inv( - self.a.square_layout()?, - self.a.as_allocated_mut()?, - &self.ipiv, - )?; - Ok(self.a) - } -} - -impl Inverse for LUFactorized -where - A: Scalar + Lapack, - S: Data + RawDataClone, -{ - type Output = Array2; - - fn inv(&self) -> Result> { - // Preserve the existing layout. This is required to obtain the correct - // result, because the result of `A::inv` is layout-dependent. - let a = if self.a.is_standard_layout() { - replicate(&self.a) - } else { - replicate(&self.a.t()).reversed_axes() - }; - let f = LUFactorized { - a, - ipiv: self.ipiv.clone(), - }; - f.inv_into() - } -} - -impl InverseInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut + RawDataClone, -{ - type Output = Self; - - fn inv_into(self) -> Result { - let f = self.factorize_into()?; - f.inv_into() - } -} - -impl Inverse for ArrayBase -where - A: Scalar + Lapack, - Si: Data, -{ - type Output = Array2; - - fn inv(&self) -> Result { - let f = self.factorize()?; - f.inv_into() - } -} - -/// An interface for calculating determinants of matrix refs. -pub trait Determinant { - /// Computes the determinant of the matrix. - fn det(&self) -> Result { - let (sign, ln_det) = self.sln_det()?; - Ok(sign * A::from_real(Float::exp(ln_det))) - } - - /// Computes the `(sign, natural_log)` of the determinant of the matrix. - /// - /// For real matrices, `sign` is `1`, `0`, or `-1`. For complex matrices, - /// `sign` is `0` or a complex number with absolute value 1. The - /// `natural_log` is the natural logarithm of the absolute value of the - /// determinant. If the determinant is zero, `sign` is 0 and `natural_log` - /// is negative infinity. - /// - /// To obtain the determinant, you can compute `sign * natural_log.exp()` - /// or just call `.det()` instead. - /// - /// This method is more robust than `.det()` to very small or very large - /// determinants since it returns the natural logarithm of the determinant - /// rather than the determinant itself. - fn sln_det(&self) -> Result<(A, A::Real)>; -} - -/// An interface for calculating determinants of matrices. -pub trait DeterminantInto: Sized { - /// Computes the determinant of the matrix. - fn det_into(self) -> Result { - let (sign, ln_det) = self.sln_det_into()?; - Ok(sign * A::from_real(Float::exp(ln_det))) - } - - /// Computes the `(sign, natural_log)` of the determinant of the matrix. - /// - /// For real matrices, `sign` is `1`, `0`, or `-1`. For complex matrices, - /// `sign` is `0` or a complex number with absolute value 1. The - /// `natural_log` is the natural logarithm of the absolute value of the - /// determinant. If the determinant is zero, `sign` is 0 and `natural_log` - /// is negative infinity. - /// - /// To obtain the determinant, you can compute `sign * natural_log.exp()` - /// or just call `.det_into()` instead. - /// - /// This method is more robust than `.det()` to very small or very large - /// determinants since it returns the natural logarithm of the determinant - /// rather than the determinant itself. - fn sln_det_into(self) -> Result<(A, A::Real)>; -} - -fn lu_sln_det<'a, A, P, U>(ipiv_iter: P, u_diag_iter: U) -> (A, A::Real) -where - A: Scalar + Lapack, - P: Iterator, - U: Iterator, -{ - let pivot_sign = if ipiv_iter - .enumerate() - .filter(|&(i, pivot)| pivot != i as i32 + 1) - .count() - % 2 - == 0 - { - A::one() - } else { - -A::one() - }; - let (upper_sign, ln_det) = u_diag_iter.fold( - (A::one(), A::Real::zero()), - |(upper_sign, ln_det), &elem| { - let abs_elem: A::Real = elem.abs(); - ( - upper_sign * elem / A::from_real(abs_elem), - ln_det + Float::ln(abs_elem), - ) - }, - ); - (pivot_sign * upper_sign, ln_det) -} - -impl Determinant for LUFactorized -where - A: Scalar + Lapack, - S: Data + RawDataClone, -{ - fn sln_det(&self) -> Result<(A, A::Real)> { - self.a.ensure_square()?; - Ok(lu_sln_det(self.ipiv.iter().cloned(), self.a.diag().iter())) - } -} - -impl DeterminantInto for LUFactorized -where - A: Scalar + Lapack, - S: Data + RawDataClone, -{ - fn sln_det_into(self) -> Result<(A, A::Real)> { - self.a.ensure_square()?; - Ok(lu_sln_det(self.ipiv.into_iter(), self.a.into_diag().iter())) - } -} - -impl Determinant for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn sln_det(&self) -> Result<(A, A::Real)> { - self.ensure_square()?; - match self.factorize() { - Ok(fac) => fac.sln_det(), - Err(LinalgError::Lapack(e)) - if matches!(e, lax::error::Error::LapackComputationalFailure { .. }) => - { - // The determinant is zero. - Ok((A::zero(), A::Real::neg_infinity())) - } - Err(err) => Err(err), - } - } -} - -impl DeterminantInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut + RawDataClone, -{ - fn sln_det_into(self) -> Result<(A, A::Real)> { - self.ensure_square()?; - match self.factorize_into() { - Ok(fac) => fac.sln_det_into(), - Err(LinalgError::Lapack(e)) - if matches!(e, lax::error::Error::LapackComputationalFailure { .. }) => - { - // The determinant is zero. - Ok((A::zero(), A::Real::neg_infinity())) - } - Err(err) => Err(err), - } - } -} - -/// An interface for *estimating* the reciprocal condition number of matrix refs. -pub trait ReciprocalConditionNum { - /// *Estimates* the reciprocal of the condition number of the matrix in - /// 1-norm. - /// - /// This method uses the LAPACK `*gecon` routines, which *estimate* - /// `self.inv().opnorm_one()` and then compute `rcond = 1. / - /// (self.opnorm_one() * self.inv().opnorm_one())`. - /// - /// * If `rcond` is near `0.`, the matrix is badly conditioned. - /// * If `rcond` is near `1.`, the matrix is well conditioned. - fn rcond(&self) -> Result; -} - -/// An interface for *estimating* the reciprocal condition number of matrices. -pub trait ReciprocalConditionNumInto { - /// *Estimates* the reciprocal of the condition number of the matrix in - /// 1-norm. - /// - /// This method uses the LAPACK `*gecon` routines, which *estimate* - /// `self.inv().opnorm_one()` and then compute `rcond = 1. / - /// (self.opnorm_one() * self.inv().opnorm_one())`. - /// - /// * If `rcond` is near `0.`, the matrix is badly conditioned. - /// * If `rcond` is near `1.`, the matrix is well conditioned. - fn rcond_into(self) -> Result; -} - -impl ReciprocalConditionNum for LUFactorized -where - A: Scalar + Lapack, - S: Data + RawDataClone, -{ - fn rcond(&self) -> Result { - Ok(A::rcond( - self.a.layout()?, - self.a.as_allocated()?, - self.a.opnorm_one()?, - )?) - } -} - -impl ReciprocalConditionNumInto for LUFactorized -where - A: Scalar + Lapack, - S: Data + RawDataClone, -{ - fn rcond_into(self) -> Result { - self.rcond() - } -} - -impl ReciprocalConditionNum for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn rcond(&self) -> Result { - self.factorize()?.rcond_into() - } -} - -impl ReciprocalConditionNumInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut + RawDataClone, -{ - fn rcond_into(self) -> Result { - self.factorize_into()?.rcond_into() - } -} diff --git a/ndarray-linalg/src/solveh.rs b/ndarray-linalg/src/solveh.rs deleted file mode 100644 index df0b3a6f..00000000 --- a/ndarray-linalg/src/solveh.rs +++ /dev/null @@ -1,477 +0,0 @@ -//! Solve Hermitian (or real symmetric) linear problems and invert Hermitian -//! (or real symmetric) matrices -//! -//! **Note that only the upper triangular portion of the matrix is used.** -//! -//! # Examples -//! -//! Solve `A * x = b`, where `A` is a Hermitian (or real symmetric) matrix: -//! -//! ``` -//! use ndarray::prelude::*; -//! use ndarray_linalg::SolveH; -//! -//! let a: Array2 = array![ -//! [3., 2., -1.], -//! [2., -2., 4.], -//! [-1., 4., 5.] -//! ]; -//! let b: Array1 = array![11., -12., 1.]; -//! let x = a.solveh_into(b).unwrap(); -//! assert!(x.abs_diff_eq(&array![1., 3., -2.], 1e-9)); -//! ``` -//! -//! If you are solving multiple systems of linear equations with the same -//! Hermitian or real symmetric coefficient matrix `A`, it's faster to compute -//! the factorization once at the beginning than solving directly using `A`: -//! -//! ``` -//! use ndarray::prelude::*; -//! use ndarray_linalg::*; -//! -//! /// Use fixed algorithm and seed of PRNG for reproducible test -//! let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); -//! -//! let a: Array2 = random_using((3, 3), &mut rng); -//! let f = a.factorizeh_into().unwrap(); // Factorize A (A is consumed) -//! for _ in 0..10 { -//! let b: Array1 = random_using(3, &mut rng); -//! let x = f.solveh_into(b).unwrap(); // Solve A * x = b using the factorization -//! } -//! ``` - -use ndarray::*; -use num_traits::{Float, One, Zero}; - -use crate::convert::*; -use crate::error::*; -use crate::layout::*; -use crate::types::*; - -pub use lax::{Pivot, UPLO}; - -/// An interface for solving systems of Hermitian (or real symmetric) linear equations. -/// -/// If you plan to solve many equations with the same Hermitian (or real -/// symmetric) coefficient matrix `A` but different `b` vectors, it's faster to -/// factor the `A` matrix once using the `FactorizeH` trait, and then solve -/// using the `BKFactorized` struct. -pub trait SolveH { - /// Solves a system of linear equations `A * x = b` with Hermitian (or real - /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of columns - /// of `A`. - fn solveh>(&self, b: &ArrayBase) -> Result> { - let mut b = replicate(b); - self.solveh_inplace(&mut b)?; - Ok(b) - } - - /// Solves a system of linear equations `A * x = b` with Hermitian (or real - /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of columns - /// of `A`. - fn solveh_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solveh_inplace(&mut b)?; - Ok(b) - } - - /// Solves a system of linear equations `A * x = b` with Hermitian (or real - /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. The value of `x` is also assigned to the - /// argument. - /// - /// # Panics - /// - /// Panics if the length of `b` is not the equal to the number of columns - /// of `A`. - fn solveh_inplace<'a, S: DataMut>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; -} - -/// Represents the Bunch–Kaufman factorization of a Hermitian (or real -/// symmetric) matrix as `A = P * U * D * U^H * P^T`. -pub struct BKFactorized { - pub a: ArrayBase, - pub ipiv: Pivot, -} - -impl SolveH for BKFactorized -where - A: Scalar + Lapack, - S: Data, -{ - fn solveh_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - assert_eq!( - rhs.len(), - self.a.len_of(Axis(1)), - "The length of `rhs` must be compatible with the shape of the factored matrix.", - ); - A::solveh( - self.a.square_layout()?, - UPLO::Upper, - self.a.as_allocated()?, - &self.ipiv, - rhs.as_slice_mut().unwrap(), - )?; - Ok(rhs) - } -} - -impl SolveH for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn solveh_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorizeh()?; - f.solveh_inplace(rhs) - } -} - -/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or -/// real symmetric) matrix refs. -pub trait FactorizeH { - /// Computes the Bunch–Kaufman factorization of a Hermitian (or real - /// symmetric) matrix. - fn factorizeh(&self) -> Result>; -} - -/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or -/// real symmetric) matrices. -pub trait FactorizeHInto { - /// Computes the Bunch–Kaufman factorization of a Hermitian (or real - /// symmetric) matrix. - fn factorizeh_into(self) -> Result>; -} - -impl FactorizeHInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - fn factorizeh_into(mut self) -> Result> { - let ipiv = A::bk(self.square_layout()?, UPLO::Upper, self.as_allocated_mut()?)?; - Ok(BKFactorized { a: self, ipiv }) - } -} - -impl FactorizeH> for ArrayBase -where - A: Scalar + Lapack, - Si: Data, -{ - fn factorizeh(&self) -> Result>> { - let mut a: Array2 = replicate(self); - let ipiv = A::bk(a.square_layout()?, UPLO::Upper, a.as_allocated_mut()?)?; - Ok(BKFactorized { a, ipiv }) - } -} - -/// An interface for inverting Hermitian (or real symmetric) matrix refs. -pub trait InverseH { - type Output; - /// Computes the inverse of the Hermitian (or real symmetric) matrix. - fn invh(&self) -> Result; -} - -/// An interface for inverting Hermitian (or real symmetric) matrices. -pub trait InverseHInto { - type Output; - /// Computes the inverse of the Hermitian (or real symmetric) matrix. - fn invh_into(self) -> Result; -} - -impl InverseHInto for BKFactorized -where - A: Scalar + Lapack, - S: DataMut, -{ - type Output = ArrayBase; - - fn invh_into(mut self) -> Result> { - A::invh( - self.a.square_layout()?, - UPLO::Upper, - self.a.as_allocated_mut()?, - &self.ipiv, - )?; - triangular_fill_hermitian(&mut self.a, UPLO::Upper); - Ok(self.a) - } -} - -impl InverseH for BKFactorized -where - A: Scalar + Lapack, - S: Data, -{ - type Output = Array2; - - fn invh(&self) -> Result { - let f = BKFactorized { - a: replicate(&self.a), - ipiv: self.ipiv.clone(), - }; - f.invh_into() - } -} - -impl InverseHInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type Output = Self; - - fn invh_into(self) -> Result { - let f = self.factorizeh_into()?; - f.invh_into() - } -} - -impl InverseH for ArrayBase -where - A: Scalar + Lapack, - Si: Data, -{ - type Output = Array2; - - fn invh(&self) -> Result { - let f = self.factorizeh()?; - f.invh_into() - } -} - -/// An interface for calculating determinants of Hermitian (or real symmetric) matrix refs. -pub trait DeterminantH { - /// The element type of the matrix. - type Elem: Scalar; - - /// Computes the determinant of the Hermitian (or real symmetric) matrix. - fn deth(&self) -> Result<::Real>; - - /// Computes the `(sign, natural_log)` of the determinant of the Hermitian - /// (or real symmetric) matrix. - /// - /// The `natural_log` is the natural logarithm of the absolute value of the - /// determinant. If the determinant is zero, `sign` is 0 and `natural_log` - /// is negative infinity. - /// - /// To obtain the determinant, you can compute `sign * natural_log.exp()` - /// or just call `.deth()` instead. - /// - /// This method is more robust than `.deth()` to very small or very large - /// determinants since it returns the natural logarithm of the determinant - /// rather than the determinant itself. - fn sln_deth(&self) -> Result<(::Real, ::Real)>; -} - -/// An interface for calculating determinants of Hermitian (or real symmetric) matrices. -pub trait DeterminantHInto { - /// The element type of the matrix. - type Elem: Scalar; - - /// Computes the determinant of the Hermitian (or real symmetric) matrix. - fn deth_into(self) -> Result<::Real>; - - /// Computes the `(sign, natural_log)` of the determinant of the Hermitian - /// (or real symmetric) matrix. - /// - /// The `natural_log` is the natural logarithm of the absolute value of the - /// determinant. If the determinant is zero, `sign` is 0 and `natural_log` - /// is negative infinity. - /// - /// To obtain the determinant, you can compute `sign * natural_log.exp()` - /// or just call `.deth_into()` instead. - /// - /// This method is more robust than `.deth_into()` to very small or very - /// large determinants since it returns the natural logarithm of the - /// determinant rather than the determinant itself. - fn sln_deth_into(self) -> Result<(::Real, ::Real)>; -} - -/// Returns the sign and natural log of the determinant. -fn bk_sln_det(uplo: UPLO, ipiv_iter: P, a: &ArrayBase) -> (A::Real, A::Real) -where - P: Iterator, - S: Data, - A: Scalar + Lapack, -{ - let layout = a.layout().unwrap(); - let mut sign = A::Real::one(); - let mut ln_det = A::Real::zero(); - let mut ipiv_enum = ipiv_iter.enumerate(); - while let Some((k, ipiv_k)) = ipiv_enum.next() { - debug_assert!(k < a.nrows() && k < a.ncols()); - if ipiv_k > 0 { - // 1x1 block at k, must be real. - let elem = unsafe { a.uget((k, k)) }.re(); - debug_assert_eq!(elem.im(), Zero::zero()); - sign *= elem.signum(); - ln_det += Float::ln(Float::abs(elem)); - } else { - // 2x2 block at k..k+2. - - // Upper left diagonal elem, must be real. - let upper_diag = unsafe { a.uget((k, k)) }.re(); - debug_assert_eq!(upper_diag.im(), Zero::zero()); - - // Lower right diagonal elem, must be real. - let lower_diag = unsafe { a.uget((k + 1, k + 1)) }.re(); - debug_assert_eq!(lower_diag.im(), Zero::zero()); - - // Off-diagonal elements, can be complex. - let off_diag = match layout { - MatrixLayout::C { .. } => match uplo { - UPLO::Upper => unsafe { a.uget((k + 1, k)) }, - UPLO::Lower => unsafe { a.uget((k, k + 1)) }, - }, - MatrixLayout::F { .. } => match uplo { - UPLO::Upper => unsafe { a.uget((k, k + 1)) }, - UPLO::Lower => unsafe { a.uget((k + 1, k)) }, - }, - }; - - // Determinant of 2x2 block. - let block_det = upper_diag * lower_diag - off_diag.square(); - sign *= block_det.signum(); - ln_det += Float::ln(Float::abs(block_det)); - - // Skip the k+1 ipiv value. - ipiv_enum.next(); - } - } - (sign, ln_det) -} - -impl BKFactorized -where - A: Scalar + Lapack, - S: Data, -{ - /// Computes the determinant of the factorized Hermitian (or real - /// symmetric) matrix. - pub fn deth(&self) -> A::Real { - let (sign, ln_det) = self.sln_deth(); - sign * Float::exp(ln_det) - } - - /// Computes the `(sign, natural_log)` of the determinant of the factorized - /// Hermitian (or real symmetric) matrix. - /// - /// The `natural_log` is the natural logarithm of the absolute value of the - /// determinant. If the determinant is zero, `sign` is 0 and `natural_log` - /// is negative infinity. - /// - /// To obtain the determinant, you can compute `sign * natural_log.exp()` - /// or just call `.deth()` instead. - /// - /// This method is more robust than `.deth()` to very small or very large - /// determinants since it returns the natural logarithm of the determinant - /// rather than the determinant itself. - pub fn sln_deth(&self) -> (A::Real, A::Real) { - bk_sln_det(UPLO::Upper, self.ipiv.iter().cloned(), &self.a) - } - - /// Computes the determinant of the factorized Hermitian (or real - /// symmetric) matrix. - pub fn deth_into(self) -> A::Real { - let (sign, ln_det) = self.sln_deth_into(); - sign * Float::exp(ln_det) - } - - /// Computes the `(sign, natural_log)` of the determinant of the factorized - /// Hermitian (or real symmetric) matrix. - /// - /// The `natural_log` is the natural logarithm of the absolute value of the - /// determinant. If the determinant is zero, `sign` is 0 and `natural_log` - /// is negative infinity. - /// - /// To obtain the determinant, you can compute `sign * natural_log.exp()` - /// or just call `.deth_into()` instead. - /// - /// This method is more robust than `.deth_into()` to very small or very - /// large determinants since it returns the natural logarithm of the - /// determinant rather than the determinant itself. - pub fn sln_deth_into(self) -> (A::Real, A::Real) { - bk_sln_det(UPLO::Upper, self.ipiv.into_iter(), &self.a) - } -} - -impl DeterminantH for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type Elem = A; - - fn deth(&self) -> Result { - let (sign, ln_det) = self.sln_deth()?; - Ok(sign * Float::exp(ln_det)) - } - - fn sln_deth(&self) -> Result<(A::Real, A::Real)> { - match self.factorizeh() { - Ok(fac) => Ok(fac.sln_deth()), - Err(LinalgError::Lapack(e)) - if matches!(e, lax::error::Error::LapackComputationalFailure { .. }) => - { - // Determinant is zero. - Ok((A::Real::zero(), A::Real::neg_infinity())) - } - Err(err) => Err(err), - } - } -} - -impl DeterminantHInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type Elem = A; - - fn deth_into(self) -> Result { - let (sign, ln_det) = self.sln_deth_into()?; - Ok(sign * Float::exp(ln_det)) - } - - fn sln_deth_into(self) -> Result<(A::Real, A::Real)> { - match self.factorizeh_into() { - Ok(fac) => Ok(fac.sln_deth_into()), - Err(LinalgError::Lapack(e)) - if matches!(e, lax::error::Error::LapackComputationalFailure { .. }) => - { - // Determinant is zero. - Ok((A::Real::zero(), A::Real::neg_infinity())) - } - Err(err) => Err(err), - } - } -} diff --git a/ndarray-linalg/src/svd.rs b/ndarray-linalg/src/svd.rs deleted file mode 100644 index 5c9d59b1..00000000 --- a/ndarray-linalg/src/svd.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! Singular-value decomposition (SVD) -//! -//! [Wikipedia article on SVD](https://en.wikipedia.org/wiki/Singular_value_decomposition) - -use crate::{convert::*, error::*, layout::*, types::*}; -use ndarray::*; - -/// singular-value decomposition of matrix reference -pub trait SVD { - type U; - type VT; - type Sigma; - fn svd( - &self, - calc_u: bool, - calc_vt: bool, - ) -> Result<(Option, Self::Sigma, Option)>; -} - -/// singular-value decomposition -pub trait SVDInto { - type U; - type VT; - type Sigma; - fn svd_into( - self, - calc_u: bool, - calc_vt: bool, - ) -> Result<(Option, Self::Sigma, Option)>; -} - -/// singular-value decomposition for mutable reference of matrix -pub trait SVDInplace { - type U; - type VT; - type Sigma; - fn svd_inplace( - &mut self, - calc_u: bool, - calc_vt: bool, - ) -> Result<(Option, Self::Sigma, Option)>; -} - -impl SVDInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type U = Array2; - type VT = Array2; - type Sigma = Array1; - - fn svd_into( - mut self, - calc_u: bool, - calc_vt: bool, - ) -> Result<(Option, Self::Sigma, Option)> { - self.svd_inplace(calc_u, calc_vt) - } -} - -impl SVD for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type U = Array2; - type VT = Array2; - type Sigma = Array1; - - fn svd( - &self, - calc_u: bool, - calc_vt: bool, - ) -> Result<(Option, Self::Sigma, Option)> { - let a = self.to_owned(); - a.svd_into(calc_u, calc_vt) - } -} - -impl SVDInplace for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type U = Array2; - type VT = Array2; - type Sigma = Array1; - - fn svd_inplace( - &mut self, - calc_u: bool, - calc_vt: bool, - ) -> Result<(Option, Self::Sigma, Option)> { - let l = self.layout()?; - let svd_res = A::svd(l, calc_u, calc_vt, self.as_allocated_mut()?)?; - let (n, m) = l.size(); - - let u = svd_res.u.map(|u| into_matrix(l.resized(n, n), u).unwrap()); - let vt = svd_res - .vt - .map(|vt| into_matrix(l.resized(m, m), vt).unwrap()); - let s = ArrayBase::from(svd_res.s); - Ok((u, s, vt)) - } -} diff --git a/ndarray-linalg/src/svddc.rs b/ndarray-linalg/src/svddc.rs deleted file mode 100644 index 0b0ae237..00000000 --- a/ndarray-linalg/src/svddc.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! Singular-value decomposition (SVD) by divide-and-conquer (?gesdd) - -use super::{convert::*, error::*, layout::*, types::*}; -use ndarray::*; - -pub use lax::JobSvd; - -/// Singular-value decomposition of matrix (copying) by divide-and-conquer -pub trait SVDDC { - type U; - type VT; - type Sigma; - fn svddc(&self, uvt_flag: JobSvd) -> Result<(Option, Self::Sigma, Option)>; -} - -/// Singular-value decomposition of matrix by divide-and-conquer -pub trait SVDDCInto { - type U; - type VT; - type Sigma; - fn svddc_into( - self, - uvt_flag: JobSvd, - ) -> Result<(Option, Self::Sigma, Option)>; -} - -/// Singular-value decomposition of matrix reference by divide-and-conquer -pub trait SVDDCInplace { - type U; - type VT; - type Sigma; - fn svddc_inplace( - &mut self, - uvt_flag: JobSvd, - ) -> Result<(Option, Self::Sigma, Option)>; -} - -impl SVDDC for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - type U = Array2; - type VT = Array2; - type Sigma = Array1; - - fn svddc(&self, uvt_flag: JobSvd) -> Result<(Option, Self::Sigma, Option)> { - self.to_owned().svddc_into(uvt_flag) - } -} - -impl SVDDCInto for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type U = Array2; - type VT = Array2; - type Sigma = Array1; - - fn svddc_into( - mut self, - uvt_flag: JobSvd, - ) -> Result<(Option, Self::Sigma, Option)> { - self.svddc_inplace(uvt_flag) - } -} - -impl SVDDCInplace for ArrayBase -where - A: Scalar + Lapack, - S: DataMut, -{ - type U = Array2; - type VT = Array2; - type Sigma = Array1; - - fn svddc_inplace( - &mut self, - uvt_flag: JobSvd, - ) -> Result<(Option, Self::Sigma, Option)> { - let l = self.layout()?; - let svd_res = A::svddc(l, uvt_flag, self.as_allocated_mut()?)?; - let (m, n) = l.size(); - let k = m.min(n); - - let (u_col, vt_row) = match uvt_flag { - JobSvd::All => (m, n), - JobSvd::Some => (k, k), - JobSvd::None => (0, 0), - }; - - let u = svd_res - .u - .map(|u| into_matrix(l.resized(m, u_col), u).unwrap()); - - let vt = svd_res - .vt - .map(|vt| into_matrix(l.resized(vt_row, n), vt).unwrap()); - - let s = ArrayBase::from(svd_res.s); - Ok((u, s, vt)) - } -} diff --git a/ndarray-linalg/src/trace.rs b/ndarray-linalg/src/trace.rs deleted file mode 100644 index feb119f2..00000000 --- a/ndarray-linalg/src/trace.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! Trace calculation - -use ndarray::*; -use std::iter::Sum; - -use super::error::*; -use super::types::*; - -pub trait Trace { - type Output; - fn trace(&self) -> Result; -} - -impl Trace for ArrayBase -where - A: Scalar + Sum, - S: Data, -{ - type Output = A; - - fn trace(&self) -> Result { - let n = match self.is_square() { - true => Ok(self.nrows()), - false => Err(LinalgError::NotSquare { - rows: self.nrows() as i32, - cols: self.ncols() as i32, - }), - }?; - Ok((0..n as usize).map(|i| self[(i, i)]).sum()) - } -} diff --git a/ndarray-linalg/src/triangular.rs b/ndarray-linalg/src/triangular.rs deleted file mode 100644 index 2741d7b0..00000000 --- a/ndarray-linalg/src/triangular.rs +++ /dev/null @@ -1,184 +0,0 @@ -//! Methods for triangular matrices - -use lax::*; -use ndarray::*; -use num_traits::Zero; - -use super::convert::*; -use super::error::*; -use super::layout::*; -use super::types::*; - -pub use lax::Diag; - -/// solve a triangular system with upper triangular matrix -pub trait SolveTriangular -where - A: Scalar + Lapack, - S: Data, - D: Dimension, -{ - fn solve_triangular(&self, uplo: UPLO, diag: Diag, b: &ArrayBase) -> Result>; -} - -/// solve a triangular system with upper triangular matrix -pub trait SolveTriangularInto -where - S: DataMut, - D: Dimension, -{ - fn solve_triangular_into( - &self, - uplo: UPLO, - diag: Diag, - b: ArrayBase, - ) -> Result>; -} - -/// solve a triangular system with upper triangular matrix -pub trait SolveTriangularInplace -where - S: DataMut, - D: Dimension, -{ - fn solve_triangular_inplace<'a>( - &self, - uplo: UPLO, - diag: Diag, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; -} - -impl SolveTriangularInto for ArrayBase -where - A: Scalar + Lapack, - Si: Data, - So: DataMut + DataOwned, -{ - fn solve_triangular_into( - &self, - uplo: UPLO, - diag: Diag, - mut b: ArrayBase, - ) -> Result> { - self.solve_triangular_inplace(uplo, diag, &mut b)?; - Ok(b) - } -} - -impl SolveTriangularInplace for ArrayBase -where - A: Scalar + Lapack, - Si: Data, - So: DataMut + DataOwned, -{ - fn solve_triangular_inplace<'a>( - &self, - uplo: UPLO, - diag: Diag, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> { - let la = self.layout()?; - let a_ = self.as_allocated()?; - let lb = b.layout()?; - if !la.same_order(&lb) { - transpose_data(b)?; - } - let lb = b.layout()?; - A::solve_triangular(la, lb, uplo, diag, a_, b.as_allocated_mut()?)?; - Ok(b) - } -} - -impl SolveTriangular for ArrayBase -where - A: Scalar + Lapack, - Si: Data, - So: DataMut + DataOwned, -{ - fn solve_triangular( - &self, - uplo: UPLO, - diag: Diag, - b: &ArrayBase, - ) -> Result> { - let b = replicate(b); - self.solve_triangular_into(uplo, diag, b) - } -} - -impl SolveTriangularInto for ArrayBase -where - A: Scalar + Lapack, - Si: Data, - So: DataMut + DataOwned, -{ - fn solve_triangular_into( - &self, - uplo: UPLO, - diag: Diag, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let b = self.solve_triangular_into(uplo, diag, b)?; - Ok(flatten(b)) - } -} - -impl SolveTriangular for ArrayBase -where - A: Scalar + Lapack, - Si: Data, - So: DataMut + DataOwned, -{ - fn solve_triangular( - &self, - uplo: UPLO, - diag: Diag, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_triangular_into(uplo, diag, b) - } -} - -pub trait IntoTriangular { - fn into_triangular(self, uplo: UPLO) -> T; -} - -impl<'a, A, S> IntoTriangular<&'a mut ArrayBase> for &'a mut ArrayBase -where - A: Zero, - S: DataMut, -{ - fn into_triangular(self, uplo: UPLO) -> &'a mut ArrayBase { - match uplo { - UPLO::Upper => { - for ((i, j), val) in self.indexed_iter_mut() { - if i > j { - *val = A::zero(); - } - } - } - UPLO::Lower => { - for ((i, j), val) in self.indexed_iter_mut() { - if i < j { - *val = A::zero(); - } - } - } - } - self - } -} - -impl IntoTriangular> for ArrayBase -where - A: Zero, - S: DataMut, -{ - fn into_triangular(mut self, uplo: UPLO) -> ArrayBase { - (&mut self).into_triangular(uplo); - self - } -} diff --git a/ndarray-linalg/src/tridiagonal.rs b/ndarray-linalg/src/tridiagonal.rs deleted file mode 100644 index b5aebbf2..00000000 --- a/ndarray-linalg/src/tridiagonal.rs +++ /dev/null @@ -1,695 +0,0 @@ -//! Vectors as a Tridiagonal matrix -//! & -//! Methods for tridiagonal matrices - -use super::convert::*; -use super::error::*; -use super::layout::*; -use cauchy::Scalar; -use lax::*; -use ndarray::*; -use num_traits::One; - -pub use lax::{LUFactorizedTridiagonal, Tridiagonal}; - -/// An interface for making a Tridiagonal struct. -pub trait ExtractTridiagonal { - /// Extract tridiagonal elements and layout of the raw matrix. - /// - /// If the raw matrix has some non-tridiagonal elements, - /// they will be ignored. - /// - /// The shape of raw matrix should be equal to or larger than (2, 2). - fn extract_tridiagonal(&self) -> Result>; -} - -impl ExtractTridiagonal for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn extract_tridiagonal(&self) -> Result> { - let l = self.square_layout()?; - let (n, _) = l.size(); - if n < 2 { - return Err(LinalgError::NotStandardShape { - obj: "Tridiagonal", - rows: 1, - cols: 1, - }); - } - - let dl = self.slice(s![1..n, 0..n - 1]).diag().to_vec(); - let d = self.diag().to_vec(); - let du = self.slice(s![0..n - 1, 1..n]).diag().to_vec(); - Ok(Tridiagonal { l, dl, d, du }) - } -} - -pub trait SolveTridiagonal { - /// Solves a system of linear equations `A * x = b` with tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. - fn solve_tridiagonal>(&self, b: &ArrayBase) -> Result>; - /// Solves a system of linear equations `A * x = b` with tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. - fn solve_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result>; - /// Solves a system of linear equations `A^T * x = b` with tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. - fn solve_t_tridiagonal>(&self, b: &ArrayBase) -> Result>; - /// Solves a system of linear equations `A^T * x = b` with tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. - fn solve_t_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result>; - /// Solves a system of linear equations `A^H * x = b` with tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. - fn solve_h_tridiagonal>(&self, b: &ArrayBase) -> Result>; - /// Solves a system of linear equations `A^H * x = b` with tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. - fn solve_h_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result>; -} - -pub trait SolveTridiagonalInplace { - /// Solves a system of linear equations `A * x = b` tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. The value of `x` is also assigned to the - /// argument. - fn solve_tridiagonal_inplace<'a, S: DataMut>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; - /// Solves a system of linear equations `A^T * x = b` tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. The value of `x` is also assigned to the - /// argument. - fn solve_t_tridiagonal_inplace<'a, S: DataMut>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; - /// Solves a system of linear equations `A^H * x = b` tridiagonal - /// matrix `A`, where `A` is `self`, `b` is the argument, and - /// `x` is the successful result. The value of `x` is also assigned to the - /// argument. - fn solve_h_tridiagonal_inplace<'a, S: DataMut>( - &self, - b: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase>; -} - -impl SolveTridiagonal for LUFactorizedTridiagonal -where - A: Scalar + Lapack, -{ - fn solve_tridiagonal>(&self, b: &ArrayBase) -> Result> { - let mut b = replicate(b); - self.solve_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_t_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let mut b = replicate(b); - self.solve_t_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_t_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_t_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_h_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let mut b = replicate(b); - self.solve_h_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_h_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_h_tridiagonal_inplace(&mut b)?; - Ok(b) - } -} - -impl SolveTridiagonal for Tridiagonal -where - A: Scalar + Lapack, -{ - fn solve_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let mut b = replicate(b); - self.solve_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_t_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let mut b = replicate(b); - self.solve_t_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_t_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_t_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_h_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let mut b = replicate(b); - self.solve_h_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_h_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_h_tridiagonal_inplace(&mut b)?; - Ok(b) - } -} - -impl SolveTridiagonal for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn solve_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let mut b = replicate(b); - self.solve_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_t_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let mut b = replicate(b); - self.solve_t_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_t_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_t_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_h_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let mut b = replicate(b); - self.solve_h_tridiagonal_inplace(&mut b)?; - Ok(b) - } - fn solve_h_tridiagonal_into>( - &self, - mut b: ArrayBase, - ) -> Result> { - self.solve_h_tridiagonal_inplace(&mut b)?; - Ok(b) - } -} - -impl SolveTridiagonalInplace for LUFactorizedTridiagonal -where - A: Scalar + Lapack, -{ - fn solve_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - A::solve_tridiagonal( - self, - rhs.layout()?, - Transpose::No, - rhs.as_slice_mut().unwrap(), - )?; - Ok(rhs) - } - fn solve_t_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - A::solve_tridiagonal( - self, - rhs.layout()?, - Transpose::Transpose, - rhs.as_slice_mut().unwrap(), - )?; - Ok(rhs) - } - fn solve_h_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - A::solve_tridiagonal( - self, - rhs.layout()?, - Transpose::Hermite, - rhs.as_slice_mut().unwrap(), - )?; - Ok(rhs) - } -} - -impl SolveTridiagonalInplace for Tridiagonal -where - A: Scalar + Lapack, -{ - fn solve_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize_tridiagonal()?; - f.solve_tridiagonal_inplace(rhs) - } - fn solve_t_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize_tridiagonal()?; - f.solve_t_tridiagonal_inplace(rhs) - } - fn solve_h_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize_tridiagonal()?; - f.solve_h_tridiagonal_inplace(rhs) - } -} - -impl SolveTridiagonalInplace for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn solve_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize_tridiagonal()?; - f.solve_tridiagonal_inplace(rhs) - } - fn solve_t_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize_tridiagonal()?; - f.solve_t_tridiagonal_inplace(rhs) - } - fn solve_h_tridiagonal_inplace<'a, Sb>( - &self, - rhs: &'a mut ArrayBase, - ) -> Result<&'a mut ArrayBase> - where - Sb: DataMut, - { - let f = self.factorize_tridiagonal()?; - f.solve_h_tridiagonal_inplace(rhs) - } -} - -impl SolveTridiagonal for LUFactorizedTridiagonal -where - A: Scalar + Lapack, -{ - fn solve_tridiagonal>(&self, b: &ArrayBase) -> Result> { - let b = b.to_owned(); - self.solve_tridiagonal_into(b) - } - fn solve_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let b = self.solve_tridiagonal_into(b)?; - Ok(flatten(b)) - } - fn solve_t_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_t_tridiagonal_into(b) - } - fn solve_t_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let b = self.solve_t_tridiagonal_into(b)?; - Ok(flatten(b)) - } - fn solve_h_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_h_tridiagonal_into(b) - } - fn solve_h_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let b = self.solve_h_tridiagonal_into(b)?; - Ok(flatten(b)) - } -} - -impl SolveTridiagonal for Tridiagonal -where - A: Scalar + Lapack, -{ - fn solve_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_tridiagonal_into(b) - } - fn solve_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let f = self.factorize_tridiagonal()?; - let b = f.solve_tridiagonal_into(b)?; - Ok(flatten(b)) - } - fn solve_t_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_t_tridiagonal_into(b) - } - fn solve_t_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let f = self.factorize_tridiagonal()?; - let b = f.solve_t_tridiagonal_into(b)?; - Ok(flatten(b)) - } - fn solve_h_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_h_tridiagonal_into(b) - } - fn solve_h_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let f = self.factorize_tridiagonal()?; - let b = f.solve_h_tridiagonal_into(b)?; - Ok(flatten(b)) - } -} - -impl SolveTridiagonal for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn solve_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_tridiagonal_into(b) - } - fn solve_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let f = self.factorize_tridiagonal()?; - let b = f.solve_tridiagonal_into(b)?; - Ok(flatten(b)) - } - fn solve_t_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_t_tridiagonal_into(b) - } - fn solve_t_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let f = self.factorize_tridiagonal()?; - let b = f.solve_t_tridiagonal_into(b)?; - Ok(flatten(b)) - } - fn solve_h_tridiagonal>( - &self, - b: &ArrayBase, - ) -> Result> { - let b = b.to_owned(); - self.solve_h_tridiagonal_into(b) - } - fn solve_h_tridiagonal_into>( - &self, - b: ArrayBase, - ) -> Result> { - let b = into_col(b); - let f = self.factorize_tridiagonal()?; - let b = f.solve_h_tridiagonal_into(b)?; - Ok(flatten(b)) - } -} - -/// An interface for computing LU factorizations of tridiagonal matrix refs. -pub trait FactorizeTridiagonal { - /// Computes the LU factorization `A = P*L*U`, where `P` is a permutation - /// matrix. - fn factorize_tridiagonal(&self) -> Result>; -} - -/// An interface for computing LU factorizations of tridiagonal matrices. -pub trait FactorizeTridiagonalInto { - /// Computes the LU factorization `A = P*L*U`, where `P` is a permutation - /// matrix. - fn factorize_tridiagonal_into(self) -> Result>; -} - -impl FactorizeTridiagonalInto for Tridiagonal -where - A: Scalar + Lapack, -{ - fn factorize_tridiagonal_into(self) -> Result> { - Ok(A::lu_tridiagonal(self)?) - } -} - -impl FactorizeTridiagonal for Tridiagonal -where - A: Scalar + Lapack, -{ - fn factorize_tridiagonal(&self) -> Result> { - let a = self.clone(); - Ok(A::lu_tridiagonal(a)?) - } -} - -impl FactorizeTridiagonal for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn factorize_tridiagonal(&self) -> Result> { - let a = self.extract_tridiagonal()?; - Ok(A::lu_tridiagonal(a)?) - } -} - -/// Calculates the recurrent relation, -/// f_k = a_k * f_{k-1} - c_{k-1} * b_{k-1} * f_{k-2} -/// where {a_1, a_2, ..., a_n} are diagonal elements, -/// {b_1, b_2, ..., b_{n-1}} are super-diagonal elements, and -/// {c_1, c_2, ..., c_{n-1}} are sub-diagonal elements of matrix. -/// -/// f[n] is used to calculate the determinant. -/// (https://en.wikipedia.org/wiki/Tridiagonal_matrix#Determinant) -/// -/// In the future, the vector `f` can be used to calculate the inverce matrix. -/// (https://en.wikipedia.org/wiki/Tridiagonal_matrix#Inversion) -fn rec_rel(tridiag: &Tridiagonal) -> Vec { - let n = tridiag.d.len(); - let mut f = Vec::with_capacity(n + 1); - f.push(One::one()); - f.push(tridiag.d[0]); - for i in 1..n { - f.push(tridiag.d[i] * f[i] - tridiag.dl[i - 1] * tridiag.du[i - 1] * f[i - 1]); - } - f -} - -/// An interface for calculating determinants of tridiagonal matrix refs. -pub trait DeterminantTridiagonal { - /// Computes the determinant of the matrix. - /// Unlike `.det()` of Determinant trait, this method - /// doesn't returns the natural logarithm of the determinant - /// but the determinant itself. - fn det_tridiagonal(&self) -> Result; -} - -impl DeterminantTridiagonal for Tridiagonal -where - A: Scalar, -{ - fn det_tridiagonal(&self) -> Result { - let n = self.d.len(); - Ok(rec_rel(self)[n]) - } -} - -impl DeterminantTridiagonal for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn det_tridiagonal(&self) -> Result { - let tridiag = self.extract_tridiagonal()?; - let n = tridiag.d.len(); - Ok(rec_rel(&tridiag)[n]) - } -} - -/// An interface for *estimating* the reciprocal condition number of tridiagonal matrix refs. -pub trait ReciprocalConditionNumTridiagonal { - /// *Estimates* the reciprocal of the condition number of the tridiagonal matrix in - /// 1-norm. - /// - /// This method uses the LAPACK `*gtcon` routines, which *estimate* - /// `self.inv_tridiagonal().opnorm_one()` and then compute `rcond = 1. / - /// (self.opnorm_one() * self.inv_tridiagonal().opnorm_one())`. - /// - /// * If `rcond` is near `0.`, the matrix is badly conditioned. - /// * If `rcond` is near `1.`, the matrix is well conditioned. - fn rcond_tridiagonal(&self) -> Result; -} - -/// An interface for *estimating* the reciprocal condition number of tridiagonal matrices. -pub trait ReciprocalConditionNumTridiagonalInto { - /// *Estimates* the reciprocal of the condition number of the tridiagonal matrix in - /// 1-norm. - /// - /// This method uses the LAPACK `*gtcon` routines, which *estimate* - /// `self.inv_tridiagonal().opnorm_one()` and then compute `rcond = 1. / - /// (self.opnorm_one() * self.inv_tridiagonal().opnorm_one())`. - /// - /// * If `rcond` is near `0.`, the matrix is badly conditioned. - /// * If `rcond` is near `1.`, the matrix is well conditioned. - fn rcond_tridiagonal_into(self) -> Result; -} - -impl ReciprocalConditionNumTridiagonal for LUFactorizedTridiagonal -where - A: Scalar + Lapack, -{ - fn rcond_tridiagonal(&self) -> Result { - Ok(A::rcond_tridiagonal(self)?) - } -} - -impl ReciprocalConditionNumTridiagonalInto for LUFactorizedTridiagonal -where - A: Scalar + Lapack, -{ - fn rcond_tridiagonal_into(self) -> Result { - self.rcond_tridiagonal() - } -} - -impl ReciprocalConditionNumTridiagonal for ArrayBase -where - A: Scalar + Lapack, - S: Data, -{ - fn rcond_tridiagonal(&self) -> Result { - self.factorize_tridiagonal()?.rcond_tridiagonal_into() - } -} diff --git a/ndarray-linalg/src/types.rs b/ndarray-linalg/src/types.rs deleted file mode 100644 index 57d947bc..00000000 --- a/ndarray-linalg/src/types.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Basic types and their methods for linear algebra - -pub use cauchy::Scalar; -pub use lax::Lapack; - -pub use num_complex::Complex32 as c32; -pub use num_complex::Complex64 as c64; diff --git a/ndarray-linalg/tests/arnoldi.rs b/ndarray-linalg/tests/arnoldi.rs deleted file mode 100644 index dd56e0a0..00000000 --- a/ndarray-linalg/tests/arnoldi.rs +++ /dev/null @@ -1,66 +0,0 @@ -use ndarray::*; -use ndarray_linalg::{krylov::*, *}; - -#[test] -fn aq_qh_mgs() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((5, 5), &mut rng); - let v: Array1 = random_using(5, &mut rng); - let (q, h) = arnoldi_mgs(a.clone(), v, 1e-9); - println!("A = \n{:?}", &a); - println!("Q = \n{:?}", &q); - println!("H = \n{:?}", &h); - let aq = a.dot(&q); - let qh = q.dot(&h); - println!("AQ = \n{:?}", &aq); - println!("QH = \n{:?}", &qh); - close_l2(&aq, &qh, 1e-9); -} - -#[test] -fn aq_qh_householder() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((5, 5), &mut rng); - let v: Array1 = random_using(5, &mut rng); - let (q, h) = arnoldi_mgs(a.clone(), v, 1e-9); - println!("A = \n{:?}", &a); - println!("Q = \n{:?}", &q); - println!("H = \n{:?}", &h); - let aq = a.dot(&q); - let qh = q.dot(&h); - println!("AQ = \n{:?}", &aq); - println!("QH = \n{:?}", &qh); - close_l2(&aq, &qh, 1e-9); -} - -#[test] -fn aq_qh_mgs_complex() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((5, 5), &mut rng); - let v: Array1 = random_using(5, &mut rng); - let (q, h) = arnoldi_mgs(a.clone(), v, 1e-9); - println!("A = \n{:?}", &a); - println!("Q = \n{:?}", &q); - println!("H = \n{:?}", &h); - let aq = a.dot(&q); - let qh = q.dot(&h); - println!("AQ = \n{:?}", &aq); - println!("QH = \n{:?}", &qh); - close_l2(&aq, &qh, 1e-9); -} - -#[test] -fn aq_qh_householder_complex() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((5, 5), &mut rng); - let v: Array1 = random_using(5, &mut rng); - let (q, h) = arnoldi_mgs(a.clone(), v, 1e-9); - println!("A = \n{:?}", &a); - println!("Q = \n{:?}", &q); - println!("H = \n{:?}", &h); - let aq = a.dot(&q); - let qh = q.dot(&h); - println!("AQ = \n{:?}", &aq); - println!("QH = \n{:?}", &qh); - close_l2(&aq, &qh, 1e-9); -} diff --git a/ndarray-linalg/tests/assert.rs b/ndarray-linalg/tests/assert.rs deleted file mode 100644 index bac2c5aa..00000000 --- a/ndarray-linalg/tests/assert.rs +++ /dev/null @@ -1,6 +0,0 @@ -use ndarray_linalg::assert_rclose; - -#[test] -fn assert() { - assert_rclose!(1.0, 1.0, 1e-7); -} diff --git a/ndarray-linalg/tests/cholesky.rs b/ndarray-linalg/tests/cholesky.rs deleted file mode 100644 index d3e9942b..00000000 --- a/ndarray-linalg/tests/cholesky.rs +++ /dev/null @@ -1,233 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -macro_rules! cholesky { - ($elem:ty, $rtol:expr) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a_orig: Array2<$elem> = random_hpd_using(3, &mut rng); - println!("a = \n{:?}", a_orig); - - let upper = a_orig.cholesky(UPLO::Upper).unwrap(); - assert_close_l2!( - &upper.t().mapv(|elem| elem.conj()).dot(&upper.view()), - &a_orig, - $rtol - ); - - let lower = a_orig.cholesky(UPLO::Lower).unwrap(); - assert_close_l2!( - &lower.dot(&lower.t().mapv(|elem| elem.conj())), - &a_orig, - $rtol - ); - - let a: Array2<$elem> = replicate(&a_orig); - let upper = a.cholesky_into(UPLO::Upper).unwrap(); - assert_close_l2!( - &upper.t().mapv(|elem| elem.conj()).dot(&upper.view()), - &a_orig, - $rtol - ); - - let a: Array2<$elem> = replicate(&a_orig); - let lower = a.cholesky_into(UPLO::Lower).unwrap(); - assert_close_l2!( - &lower.dot(&lower.t().mapv(|elem| elem.conj())), - &a_orig, - $rtol - ); - - let mut a: Array2<$elem> = replicate(&a_orig); - { - let upper = a.cholesky_inplace(UPLO::Upper).unwrap(); - assert_close_l2!( - &upper.t().mapv(|elem| elem.conj()).dot(&upper.view()), - &a_orig, - $rtol - ); - } - assert_close_l2!( - &a.t().mapv(|elem| elem.conj()).dot(&upper.view()), - &a_orig, - $rtol - ); - - let mut a: Array2<$elem> = replicate(&a_orig); - { - let lower = a.cholesky_inplace(UPLO::Lower).unwrap(); - assert_close_l2!( - &lower.dot(&lower.t().mapv(|elem| elem.conj())), - &a_orig, - $rtol - ); - } - assert_close_l2!(&a.dot(&lower.t().mapv(|elem| elem.conj())), &a_orig, $rtol); - } - } // paste::item - }; -} - -cholesky!(f64, 1e-9); -cholesky!(f32, 1e-5); -cholesky!(c64, 1e-9); -cholesky!(c32, 1e-5); - -macro_rules! cholesky_into_lower_upper { - ($elem:ty, $rtol:expr) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$elem> = random_hpd_using(3, &mut rng); - println!("a = \n{:?}", a); - let upper = a.cholesky(UPLO::Upper).unwrap(); - let fac_upper = a.factorizec(UPLO::Upper).unwrap(); - let fac_lower = a.factorizec(UPLO::Lower).unwrap(); - assert_close_l2!(&upper, &fac_lower.into_upper(), $rtol); - assert_close_l2!(&upper, &fac_upper.into_upper(), $rtol); - let lower = a.cholesky(UPLO::Lower).unwrap(); - let fac_upper = a.factorizec(UPLO::Upper).unwrap(); - let fac_lower = a.factorizec(UPLO::Lower).unwrap(); - assert_close_l2!(&lower, &fac_lower.into_lower(), $rtol); - assert_close_l2!(&lower, &fac_upper.into_lower(), $rtol); - } - } - }; -} - -cholesky_into_lower_upper!(f64, 1e-9); -cholesky_into_lower_upper!(f32, 1e-5); -cholesky_into_lower_upper!(c64, 1e-9); -cholesky_into_lower_upper!(c32, 1e-5); - -macro_rules! cholesky_into_inverse { - ($elem:ty, $rtol:expr) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$elem> = random_hpd_using(3, &mut rng); - println!("a = \n{:?}", a); - let inv = a.invc().unwrap(); - assert_close_l2!(&a.dot(&inv), &Array2::eye(3), $rtol); - let inv_into: Array2<$elem> = replicate(&a).invc_into().unwrap(); - assert_close_l2!(&a.dot(&inv_into), &Array2::eye(3), $rtol); - let inv_upper = a.factorizec(UPLO::Upper).unwrap().invc().unwrap(); - assert_close_l2!(&a.dot(&inv_upper), &Array2::eye(3), $rtol); - let inv_upper_into = a.factorizec(UPLO::Upper).unwrap().invc_into().unwrap(); - assert_close_l2!(&a.dot(&inv_upper_into), &Array2::eye(3), $rtol); - let inv_lower = a.factorizec(UPLO::Lower).unwrap().invc().unwrap(); - assert_close_l2!(&a.dot(&inv_lower), &Array2::eye(3), $rtol); - let inv_lower_into = a.factorizec(UPLO::Lower).unwrap().invc_into().unwrap(); - assert_close_l2!(&a.dot(&inv_lower_into), &Array2::eye(3), $rtol); - } - } - }; -} -cholesky_into_inverse!(f64, 1e-9); -cholesky_into_inverse!(f32, 1e-3); -cholesky_into_inverse!(c64, 1e-9); -cholesky_into_inverse!(c32, 1e-3); - -macro_rules! cholesky_det { - ($elem:ty, $atol:expr) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$elem> = random_hpd_using(3, &mut rng); - println!("a = \n{:?}", a); - let ln_det = a - .eigvalsh(UPLO::Upper) - .unwrap() - .mapv(|elem| elem.ln()) - .sum(); - let det = ln_det.exp(); - assert_aclose!(a.factorizec(UPLO::Upper).unwrap().detc(), det, $atol); - assert_aclose!(a.factorizec(UPLO::Upper).unwrap().ln_detc(), ln_det, $atol); - assert_aclose!(a.factorizec(UPLO::Lower).unwrap().detc_into(), det, $atol); - assert_aclose!( - a.factorizec(UPLO::Lower).unwrap().ln_detc_into(), - ln_det, - $atol - ); - assert_aclose!(a.detc().unwrap(), det, $atol); - assert_aclose!(a.ln_detc().unwrap(), ln_det, $atol); - assert_aclose!(a.clone().detc_into().unwrap(), det, $atol); - assert_aclose!(a.ln_detc_into().unwrap(), ln_det, $atol); - } - } - }; -} -cholesky_det!(f64, 1e-9); -cholesky_det!(f32, 1e-3); -cholesky_det!(c64, 1e-9); -cholesky_det!(c32, 1e-3); - -macro_rules! cholesky_solve { - ($elem:ty, $rtol:expr) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$elem> = random_hpd_using(3, &mut rng); - let x: Array1<$elem> = random_using(3, &mut rng); - let b = a.dot(&x); - println!("a = \n{:?}", a); - println!("x = \n{:?}", x); - assert_close_l2!(&a.solvec(&b).unwrap(), &x, $rtol); - assert_close_l2!(&a.solvec_into(b.clone()).unwrap(), &x, $rtol); - assert_close_l2!(&a.solvec_inplace(&mut b.clone()).unwrap(), &x, $rtol); - assert_close_l2!( - &a.factorizec(UPLO::Upper).unwrap().solvec(&b).unwrap(), - &x, - $rtol - ); - assert_close_l2!( - &a.factorizec(UPLO::Lower).unwrap().solvec(&b).unwrap(), - &x, - $rtol - ); - assert_close_l2!( - &a.factorizec(UPLO::Upper) - .unwrap() - .solvec_into(b.clone()) - .unwrap(), - &x, - $rtol - ); - assert_close_l2!( - &a.factorizec(UPLO::Lower) - .unwrap() - .solvec_into(b.clone()) - .unwrap(), - &x, - $rtol - ); - assert_close_l2!( - &a.factorizec(UPLO::Upper) - .unwrap() - .solvec_inplace(&mut b.clone()) - .unwrap(), - &x, - $rtol - ); - assert_close_l2!( - &a.factorizec(UPLO::Lower) - .unwrap() - .solvec_inplace(&mut b.clone()) - .unwrap(), - &x, - $rtol - ); - } - } - }; -} -cholesky_solve!(f64, 1e-9); -cholesky_solve!(f32, 1e-3); -cholesky_solve!(c64, 1e-9); -cholesky_solve!(c32, 1e-3); diff --git a/ndarray-linalg/tests/convert.rs b/ndarray-linalg/tests/convert.rs deleted file mode 100644 index 1e20d916..00000000 --- a/ndarray-linalg/tests/convert.rs +++ /dev/null @@ -1,11 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[test] -fn generalize() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array3 = random_using((3, 2, 4).f(), &mut rng); - let ans = a.clone(); - let a: Array3 = convert::generalize(a); - assert_eq!(a, ans); -} diff --git a/ndarray-linalg/tests/det.rs b/ndarray-linalg/tests/det.rs deleted file mode 100644 index 40dafd57..00000000 --- a/ndarray-linalg/tests/det.rs +++ /dev/null @@ -1,196 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; -use num_traits::{Float, One, Zero}; - -/// Returns the matrix with the specified `row` and `col` removed. -fn matrix_minor(a: &ArrayBase, (row, col): (usize, usize)) -> Array2 -where - A: Scalar, - S: Data, -{ - let mut select_rows = (0..a.nrows()).collect::>(); - select_rows.remove(row); - let mut select_cols = (0..a.ncols()).collect::>(); - select_cols.remove(col); - a.select(Axis(0), &select_rows) - .select(Axis(1), &select_cols) -} - -/// Computes the determinant of matrix `a`. -/// -/// Note: This implementation is written to be clearly correct so that it's -/// useful for verification, but it's very inefficient. -fn det_naive(a: &ArrayBase) -> A -where - A: Scalar, - S: Data, -{ - assert_eq!(a.nrows(), a.ncols()); - match a.ncols() { - 0 => A::one(), - 1 => a[(0, 0)], - cols => (0..cols) - .map(|col| { - let sign = if col % 2 == 0 { A::one() } else { -A::one() }; - sign * a[(0, col)] * det_naive(&matrix_minor(a, (0, col))) - }) - .fold(A::zero(), |sum, subdet| sum + subdet), - } -} - -#[test] -fn det_empty() { - macro_rules! det_empty { - ($elem:ty) => { - let a: Array2<$elem> = Array2::zeros((0, 0)); - let det = One::one(); - let (sign, ln_det) = (One::one(), Zero::zero()); - assert_eq!(a.factorize().unwrap().det().unwrap(), det); - assert_eq!(a.factorize().unwrap().sln_det().unwrap(), (sign, ln_det)); - assert_eq!(a.factorize().unwrap().det_into().unwrap(), det); - assert_eq!( - a.factorize().unwrap().sln_det_into().unwrap(), - (sign, ln_det) - ); - assert_eq!(a.det().unwrap(), det); - assert_eq!(a.sln_det().unwrap(), (sign, ln_det)); - assert_eq!(a.clone().det_into().unwrap(), det); - assert_eq!(a.sln_det_into().unwrap(), (sign, ln_det)); - }; - } - det_empty!(f64); - det_empty!(f32); - det_empty!(c64); - det_empty!(c32); -} - -#[test] -fn det_zero() { - macro_rules! det_zero { - ($elem:ty) => { - let a: Array2<$elem> = Array2::zeros((1, 1)); - let det = Zero::zero(); - let (sign, ln_det) = (Zero::zero(), Float::neg_infinity()); - assert_eq!(a.det().unwrap(), det); - assert_eq!(a.sln_det().unwrap(), (sign, ln_det)); - assert_eq!(a.clone().det_into().unwrap(), det); - assert_eq!(a.sln_det_into().unwrap(), (sign, ln_det)); - }; - } - det_zero!(f64); - det_zero!(f32); - det_zero!(c64); - det_zero!(c32); -} - -#[test] -fn det_zero_nonsquare() { - macro_rules! det_zero_nonsquare { - ($elem:ty, $shape:expr) => { - let a: Array2<$elem> = Array2::zeros($shape); - assert!(a.det().is_err()); - assert!(a.sln_det().is_err()); - assert!(a.clone().det_into().is_err()); - assert!(a.sln_det_into().is_err()); - }; - } - for &shape in &[(1, 2).into_shape_with_order(), (1, 2).f()] { - det_zero_nonsquare!(f64, shape); - det_zero_nonsquare!(f32, shape); - det_zero_nonsquare!(c64, shape); - det_zero_nonsquare!(c32, shape); - } -} - -#[test] -fn det() { - fn det_impl(a: Array2, rtol: A::Real) - where - A: Scalar + Lapack, - { - let det = det_naive(&a); - let sign = det.div_real(det.abs()); - let ln_det = Float::ln(det.abs()); - assert_rclose!(a.factorize().unwrap().det().unwrap(), det, rtol); - { - let result = a.factorize().unwrap().sln_det().unwrap(); - assert_rclose!(result.0, sign, rtol); - assert_rclose!(result.1, ln_det, rtol); - } - assert_rclose!(a.factorize().unwrap().det_into().unwrap(), det, rtol); - { - let result = a.factorize().unwrap().sln_det_into().unwrap(); - assert_rclose!(result.0, sign, rtol); - assert_rclose!(result.1, ln_det, rtol); - } - assert_rclose!(a.det().unwrap(), det, rtol); - { - let result = a.sln_det().unwrap(); - assert_rclose!(result.0, sign, rtol); - assert_rclose!(result.1, ln_det, rtol); - } - assert_rclose!(a.clone().det_into().unwrap(), det, rtol); - { - let result = a.sln_det_into().unwrap(); - assert_rclose!(result.0, sign, rtol); - assert_rclose!(result.1, ln_det, rtol); - } - } - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - for rows in 1..5 { - det_impl(random_regular_using::(rows, &mut rng), 1e-9); - det_impl(random_regular_using::(rows, &mut rng), 1e-4); - det_impl(random_regular_using::(rows, &mut rng), 1e-9); - det_impl(random_regular_using::(rows, &mut rng), 1e-4); - det_impl( - random_regular_using::(rows, &mut rng) - .t() - .to_owned(), - 1e-9, - ); - det_impl( - random_regular_using::(rows, &mut rng) - .t() - .to_owned(), - 1e-4, - ); - det_impl( - random_regular_using::(rows, &mut rng) - .t() - .to_owned(), - 1e-9, - ); - det_impl( - random_regular_using::(rows, &mut rng) - .t() - .to_owned(), - 1e-4, - ); - } -} - -#[test] -fn det_nonsquare() { - macro_rules! det_nonsquare { - ($elem:ty, $shape:expr) => { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$elem> = random_using($shape, &mut rng); - assert!(a.factorize().unwrap().det().is_err()); - assert!(a.factorize().unwrap().sln_det().is_err()); - assert!(a.factorize().unwrap().det_into().is_err()); - assert!(a.factorize().unwrap().sln_det_into().is_err()); - assert!(a.det().is_err()); - assert!(a.sln_det().is_err()); - assert!(a.clone().det_into().is_err()); - assert!(a.sln_det_into().is_err()); - }; - } - for &dims in &[(1, 0), (1, 2), (2, 1), (2, 3)] { - for &shape in &[dims.into_shape_with_order(), dims.f()] { - det_nonsquare!(f64, shape); - det_nonsquare!(f32, shape); - det_nonsquare!(c64, shape); - det_nonsquare!(c32, shape); - } - } -} diff --git a/ndarray-linalg/tests/deth.rs b/ndarray-linalg/tests/deth.rs deleted file mode 100644 index 9079c342..00000000 --- a/ndarray-linalg/tests/deth.rs +++ /dev/null @@ -1,148 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; -use num_traits::{Float, One, Zero}; - -#[test] -fn deth_empty() { - macro_rules! deth_empty { - ($elem:ty) => { - let a: Array2<$elem> = Array2::zeros((0, 0)); - assert_eq!(a.factorizeh().unwrap().deth(), One::one()); - assert_eq!( - a.factorizeh().unwrap().sln_deth(), - (One::one(), Zero::zero()) - ); - assert_eq!(a.factorizeh().unwrap().deth_into(), One::one()); - assert_eq!( - a.factorizeh().unwrap().sln_deth_into(), - (One::one(), Zero::zero()) - ); - assert_eq!(a.deth().unwrap(), One::one()); - assert_eq!(a.sln_deth().unwrap(), (One::one(), Zero::zero())); - assert_eq!(a.clone().deth_into().unwrap(), One::one()); - assert_eq!(a.sln_deth_into().unwrap(), (One::one(), Zero::zero())); - }; - } - deth_empty!(f64); - deth_empty!(f32); - deth_empty!(c64); - deth_empty!(c32); -} - -#[test] -fn deth_zero() { - macro_rules! deth_zero { - ($elem:ty) => { - let a: Array2<$elem> = Array2::zeros((1, 1)); - assert_eq!(a.deth().unwrap(), Zero::zero()); - assert_eq!(a.sln_deth().unwrap(), (Zero::zero(), Float::neg_infinity())); - assert_eq!(a.clone().deth_into().unwrap(), Zero::zero()); - assert_eq!( - a.sln_deth_into().unwrap(), - (Zero::zero(), Float::neg_infinity()) - ); - }; - } - deth_zero!(f64); - deth_zero!(f32); - deth_zero!(c64); - deth_zero!(c32); -} - -#[test] -fn deth_zero_nonsquare() { - macro_rules! deth_zero_nonsquare { - ($elem:ty, $shape:expr) => { - let a: Array2<$elem> = Array2::zeros($shape); - assert!(a.deth().is_err()); - assert!(a.sln_deth().is_err()); - assert!(a.clone().deth_into().is_err()); - assert!(a.sln_deth_into().is_err()); - }; - } - for &shape in &[(1, 2).into_shape_with_order(), (1, 2).f()] { - deth_zero_nonsquare!(f64, shape); - deth_zero_nonsquare!(f32, shape); - deth_zero_nonsquare!(c64, shape); - deth_zero_nonsquare!(c32, shape); - } -} - -#[test] -fn deth() { - macro_rules! deth { - ($elem:ty, $rows:expr, $atol:expr) => { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$elem> = random_hermite_using($rows, &mut rng); - println!("a = \n{:?}", a); - - // Compute determinant from eigenvalues. - let (sign, ln_det) = a.eigvalsh(UPLO::Upper).unwrap().iter().fold( - ( - <$elem as Scalar>::Real::one(), - <$elem as Scalar>::Real::zero(), - ), - |(sign, ln_det), eigval| (sign * eigval.signum(), ln_det + eigval.abs().ln()), - ); - let det = sign * ln_det.exp(); - assert_aclose!( - det, - a.eigvalsh(UPLO::Upper).unwrap().iter().product(), - $atol - ); - - assert_aclose!(a.factorizeh().unwrap().deth(), det, $atol); - { - let result = a.factorizeh().unwrap().sln_deth(); - assert_aclose!(result.0, sign, $atol); - assert_aclose!(result.1, ln_det, $atol); - } - assert_aclose!(a.factorizeh().unwrap().deth_into(), det, $atol); - { - let result = a.factorizeh().unwrap().sln_deth_into(); - assert_aclose!(result.0, sign, $atol); - assert_aclose!(result.1, ln_det, $atol); - } - assert_aclose!(a.deth().unwrap(), det, $atol); - { - let result = a.sln_deth().unwrap(); - assert_aclose!(result.0, sign, $atol); - assert_aclose!(result.1, ln_det, $atol); - } - assert_aclose!(a.clone().deth_into().unwrap(), det, $atol); - { - let result = a.sln_deth_into().unwrap(); - assert_aclose!(result.0, sign, $atol); - assert_aclose!(result.1, ln_det, $atol); - } - }; - } - for rows in 1..6 { - deth!(f64, rows, 1e-9); - deth!(f32, rows, 1e-3); - deth!(c64, rows, 1e-9); - deth!(c32, rows, 1e-3); - } -} - -#[test] -fn deth_nonsquare() { - macro_rules! deth_nonsquare { - ($elem:ty, $shape:expr) => { - let a: Array2<$elem> = Array2::zeros($shape); - assert!(a.factorizeh().is_err()); - assert!(a.deth().is_err()); - assert!(a.sln_deth().is_err()); - assert!(a.clone().deth_into().is_err()); - assert!(a.sln_deth_into().is_err()); - }; - } - for &dims in &[(1, 0), (1, 2), (2, 1), (2, 3)] { - for &shape in &[dims.into_shape_with_order(), dims.f()] { - deth_nonsquare!(f64, shape); - deth_nonsquare!(f32, shape); - deth_nonsquare!(c64, shape); - deth_nonsquare!(c32, shape); - } - } -} diff --git a/ndarray-linalg/tests/diag.rs b/ndarray-linalg/tests/diag.rs deleted file mode 100644 index 9d391ca2..00000000 --- a/ndarray-linalg/tests/diag.rs +++ /dev/null @@ -1,28 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[test] -fn diag_1d() { - let d = arr1(&[1.0, 2.0]); - let v = arr1(&[1.0, 1.0]); - let dv = d.into_diagonal().apply(&v); - assert_close_l2!(&dv, &arr1(&[1.0, 2.0]), 1e-7); -} - -#[test] -fn diag_2d() { - let d = arr1(&[1.0, 2.0]); - let m = arr2(&[[1.0, 1.0], [1.0, 1.0]]); - let dm = d.into_diagonal().apply2(&m); - println!("dm = {:?}", dm); - assert_close_l2!(&dm, &arr2(&[[1.0, 1.0], [2.0, 2.0]]), 1e-7); -} - -#[test] -fn diag_2d_multi() { - let d = arr1(&[1.0, 2.0]); - let m = arr2(&[[1.0, 1.0], [1.0, 1.0]]); - let dm = d.into_diagonal().apply2_into(m); - println!("dm = {:?}", dm); - assert_close_l2!(&dm, &arr2(&[[1.0, 1.0], [2.0, 2.0]]), 1e-7); -} diff --git a/ndarray-linalg/tests/eig.rs b/ndarray-linalg/tests/eig.rs deleted file mode 100644 index 8fb40212..00000000 --- a/ndarray-linalg/tests/eig.rs +++ /dev/null @@ -1,332 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -fn sorted_eigvals(eigvals: ArrayView1<'_, T>) -> Array1 { - let mut indices: Vec = (0..eigvals.len()).collect(); - indices.sort_by(|&ind1, &ind2| { - let e1 = eigvals[ind1]; - let e2 = eigvals[ind2]; - e1.re() - .partial_cmp(&e2.re()) - .unwrap() - .then(e1.im().partial_cmp(&e2.im()).unwrap()) - }); - indices.iter().map(|&ind| eigvals[ind]).collect() -} - -// Test Av_i = e_i v_i for i = 0..n -fn test_eig( - a: ArrayView2<'_, T>, - eigs: ArrayView1<'_, T::Complex>, - vecs: ArrayView2<'_, T::Complex>, -) where - T::Complex: Lapack, -{ - println!("a\n{:+.4}", &a); - println!("eigs\n{:+.4}", &eigs); - println!("vec\n{:+.4}", &vecs); - let a: Array2 = a.map(|v| v.as_c()); - for (&e, v) in eigs.iter().zip(vecs.axis_iter(Axis(1))) { - let av = a.dot(&v); - let ev = v.mapv(|val| val * e); - println!("av = {:+.4}", &av); - println!("ev = {:+.4}", &ev); - assert_close_l2!(&av, &ev, T::real(1e-3)); - } -} - -// Test case for real Eigenvalue problem -// -// -1.01 0.86 -4.60 3.31 -4.81 -// 3.98 0.53 -7.04 5.29 3.55 -// 3.30 8.26 -3.89 8.20 -1.51 -// 4.43 4.96 -7.66 -7.33 6.18 -// 7.31 -6.43 -6.16 2.47 5.58 -// -// Eigenvalues -// ( 2.86, 10.76) ( 2.86,-10.76) ( -0.69, 4.70) ( -0.69, -4.70) -10.46 -// -// Left eigenvectors -// ( 0.04, 0.29) ( 0.04, -0.29) ( -0.13, -0.33) ( -0.13, 0.33) 0.04 -// ( 0.62, 0.00) ( 0.62, 0.00) ( 0.69, 0.00) ( 0.69, 0.00) 0.56 -// ( -0.04, -0.58) ( -0.04, 0.58) ( -0.39, -0.07) ( -0.39, 0.07) -0.13 -// ( 0.28, 0.01) ( 0.28, -0.01) ( -0.02, -0.19) ( -0.02, 0.19) -0.80 -// ( -0.04, 0.34) ( -0.04, -0.34) ( -0.40, 0.22) ( -0.40, -0.22) 0.18 -// -// Right eigenvectors -// ( 0.11, 0.17) ( 0.11, -0.17) ( 0.73, 0.00) ( 0.73, 0.00) 0.46 -// ( 0.41, -0.26) ( 0.41, 0.26) ( -0.03, -0.02) ( -0.03, 0.02) 0.34 -// ( 0.10, -0.51) ( 0.10, 0.51) ( 0.19, -0.29) ( 0.19, 0.29) 0.31 -// ( 0.40, -0.09) ( 0.40, 0.09) ( -0.08, -0.08) ( -0.08, 0.08) -0.74 -// ( 0.54, 0.00) ( 0.54, 0.00) ( -0.29, -0.49) ( -0.29, 0.49) 0.16 -// -// - https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/dgeev_ex.f.htm -// -fn test_matrix_real() -> Array2 { - array![ - [ - T::real(-1.01), - T::real(0.86), - T::real(-4.60), - T::real(3.31), - T::real(-4.81) - ], - [ - T::real(3.98), - T::real(0.53), - T::real(-7.04), - T::real(5.29), - T::real(3.55) - ], - [ - T::real(3.30), - T::real(8.26), - T::real(-3.89), - T::real(8.20), - T::real(-1.51) - ], - [ - T::real(4.43), - T::real(4.96), - T::real(-7.66), - T::real(-7.33), - T::real(6.18) - ], - [ - T::real(7.31), - T::real(-6.43), - T::real(-6.16), - T::real(2.47), - T::real(5.58) - ], - ] -} - -fn test_matrix_real_t() -> Array2 { - let orig = test_matrix_real::(); - let mut out = Array2::zeros(orig.raw_dim().f()); - out.assign(&orig); - out -} - -fn answer_eig_real() -> Array1 { - array![ - T::complex(-10.46, 0.00), - T::complex(-0.69, 4.70), - T::complex(-0.69, -4.70), - T::complex(2.86, 10.76), - T::complex(2.86, -10.76), - ] -} - -// Test case for {c,z}geev -// -// ( -3.84, 2.25) ( -8.94, -4.75) ( 8.95, -6.53) ( -9.87, 4.82) -// ( -0.66, 0.83) ( -4.40, -3.82) ( -3.50, -4.26) ( -3.15, 7.36) -// ( -3.99, -4.73) ( -5.88, -6.60) ( -3.36, -0.40) ( -0.75, 5.23) -// ( 7.74, 4.18) ( 3.66, -7.53) ( 2.58, 3.60) ( 4.59, 5.41) -// -// Eigenvalues -// ( -9.43,-12.98) ( -3.44, 12.69) ( 0.11, -3.40) ( 5.76, 7.13) -// -// Left eigenvectors -// ( 0.24, -0.18) ( 0.61, 0.00) ( -0.18, -0.33) ( 0.28, 0.09) -// ( 0.79, 0.00) ( -0.05, -0.27) ( 0.82, 0.00) ( -0.55, 0.16) -// ( 0.22, -0.27) ( -0.21, 0.53) ( -0.37, 0.15) ( 0.45, 0.09) -// ( -0.02, 0.41) ( 0.40, -0.24) ( 0.06, 0.12) ( 0.62, 0.00) -// -// Right eigenvectors -// ( 0.43, 0.33) ( 0.83, 0.00) ( 0.60, 0.00) ( -0.31, 0.03) -// ( 0.51, -0.03) ( 0.08, -0.25) ( -0.40, -0.20) ( 0.04, 0.34) -// ( 0.62, 0.00) ( -0.25, 0.28) ( -0.09, -0.48) ( 0.36, 0.06) -// ( -0.23, 0.11) ( -0.10, -0.32) ( -0.43, 0.13) ( 0.81, 0.00) -// -// - https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/zgeev_ex.f.htm -// -fn test_matrix_complex() -> Array2 { - array![ - [ - T::complex(-3.84, 2.25), - T::complex(-8.94, -4.75), - T::complex(8.95, -6.53), - T::complex(-9.87, 4.82) - ], - [ - T::complex(-0.66, 0.83), - T::complex(-4.40, -3.82), - T::complex(-3.50, -4.26), - T::complex(-3.15, 7.36) - ], - [ - T::complex(-3.99, -4.73), - T::complex(-5.88, -6.60), - T::complex(-3.36, -0.40), - T::complex(-0.75, 5.23) - ], - [ - T::complex(7.74, 4.18), - T::complex(3.66, -7.53), - T::complex(2.58, 3.60), - T::complex(4.59, 5.41) - ] - ] -} - -fn test_matrix_complex_t() -> Array2 { - let orig = test_matrix_complex::(); - let mut out = Array2::zeros(orig.raw_dim().f()); - out.assign(&orig); - out -} - -fn answer_eig_complex() -> Array1 { - array![ - T::complex(-9.43, -12.98), - T::complex(-3.44, 12.69), - T::complex(0.11, -3.40), - T::complex(5.76, 7.13) - ] -} - -// re-evaluated eigenvalues in f64 accuracy -fn answer_eigvectors_complex() -> Array2 { - array![ - [ - T::complex(0.4308565200776108, 0.32681273781262143), - T::complex(0.8256820507672813, 0.), - T::complex(0.5983959785539453, 0.), - T::complex(-0.30543190348437826, 0.03333164861799901) - ], - [ - T::complex(0.5087414602970965, -0.02883342170692809), - T::complex(0.07502916788141115, -0.2487285045091665), - T::complex(-0.40047616275207687, -0.2014492227625603), - T::complex(0.03978282815783273, 0.34450765221546126) - ], - [ - T::complex(0.6198496527657755, 0.), - T::complex(-0.24575578997801528, 0.27887240221169646), - T::complex(-0.09008001907594984, -0.4752646215391732), - T::complex(0.3583254365159844, 0.06064506988524665) - ], - [ - T::complex(-0.22692824331926856, 0.11043927846403584), - T::complex(-0.10343406372814358, -0.3192014653632327), - T::complex(-0.43484029549540404, 0.13372491785816037), - T::complex(0.8082432893178352, 0.) - ] - ] -} - -macro_rules! impl_test_real { - ($real:ty) => { - paste::item! { - #[test] - fn [<$real _eigvals >]() { - let a = test_matrix_real::<$real>(); - let (e1, _vecs) = a.eig().unwrap(); - let e2 = a.eigvals().unwrap(); - assert_close_l2!(&e1, &answer_eig_real::<$real>(), 1.0e-3); - assert_close_l2!(&e2, &answer_eig_real::<$real>(), 1.0e-3); - } - - #[test] - fn [<$real _eigvals_t>]() { - let a = test_matrix_real_t::<$real>(); - let (e1, _vecs) = a.eig().unwrap(); - assert_close_l2!( - &sorted_eigvals(e1.view()), - &sorted_eigvals(answer_eig_real::<$real>().view()), - 1.0e-3 - ); - let e2 = a.eigvals().unwrap(); - assert_close_l2!( - &sorted_eigvals(e2.view()), - &sorted_eigvals(answer_eig_real::<$real>().view()), - 1.0e-3 - ); - } - - #[test] - fn [<$real _eig>]() { - let a = test_matrix_real::<$real>(); - let (e1, vecs) = a.eig().unwrap(); - let e2 = a.eigvals().unwrap(); - test_eig(a.view(), e1.view(), vecs.view()); - test_eig(a.view(), e2.view(), vecs.view()); - } - - #[test] - fn [<$real _eig_t>]() { - let a = test_matrix_real_t::<$real>(); - let (e1, vecs) = a.eig().unwrap(); - let e2 = a.eigvals().unwrap(); - test_eig(a.view(), e1.view(), vecs.view()); - test_eig(a.view(), e2.view(), vecs.view()); - } - - } // paste::item! - }; -} - -impl_test_real!(f32); -impl_test_real!(f64); - -macro_rules! impl_test_complex { - ($complex:ty) => { - paste::item! { - #[test] - fn [<$complex _eigvals >]() { - let a = test_matrix_complex::<$complex>(); - let (e1, _vecs) = a.eig().unwrap(); - let e2 = a.eigvals().unwrap(); - assert_close_l2!(&e1, &answer_eig_complex::<$complex>(), 1.0e-3); - assert_close_l2!(&e2, &answer_eig_complex::<$complex>(), 1.0e-3); - } - - #[test] - fn [<$complex _eigvals_t>]() { - let a = test_matrix_complex_t::<$complex>(); - let (e1, _vecs) = a.eig().unwrap(); - let e2 = a.eigvals().unwrap(); - assert_close_l2!(&e1, &answer_eig_complex::<$complex>(), 1.0e-3); - assert_close_l2!(&e2, &answer_eig_complex::<$complex>(), 1.0e-3); - } - - #[test] - fn [<$complex _eigvector>]() { - let a = test_matrix_complex::<$complex>(); - let (_e, vecs) = a.eig().unwrap(); - assert_close_l2!(&vecs, &answer_eigvectors_complex::<$complex>(), 1.0e-3); - } - - #[test] - fn [<$complex _eigvector_t>]() { - let a = test_matrix_complex_t::<$complex>(); - let (_e, vecs) = a.eig().unwrap(); - assert_close_l2!(&vecs, &answer_eigvectors_complex::<$complex>(), 1.0e-3); - } - - #[test] - fn [<$complex _eig>]() { - let a = test_matrix_complex::<$complex>(); - let (e1, vecs) = a.eig().unwrap(); - let e2 = a.eigvals().unwrap(); - test_eig(a.view(), e1.view(), vecs.view()); - test_eig(a.view(), e2.view(), vecs.view()); - } - - #[test] - fn [<$complex _eig_t>]() { - let a = test_matrix_complex_t::<$complex>(); - let (e1, vecs) = a.eig().unwrap(); - let e2 = a.eigvals().unwrap(); - test_eig(a.view(), e1.view(), vecs.view()); - test_eig(a.view(), e2.view(), vecs.view()); - } - } // paste::item! - }; -} - -impl_test_complex!(c32); -impl_test_complex!(c64); diff --git a/ndarray-linalg/tests/eig_generalized.rs b/ndarray-linalg/tests/eig_generalized.rs deleted file mode 100644 index 06df81ec..00000000 --- a/ndarray-linalg/tests/eig_generalized.rs +++ /dev/null @@ -1,190 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[test] -fn generalized_eigenvalue_fmt() { - let ge0 = GeneralizedEigenvalue::Finite(0.1, (1.0, 10.0)); - assert_eq!(ge0.to_string(), "1.000e-1 (1.000e0/1.000e1)".to_string()); - - let ge1 = GeneralizedEigenvalue::Indeterminate((1.0, 0.0)); - assert_eq!(ge1.to_string(), "∞ (1.000e0/0.000e0)".to_string()); -} - -#[test] -fn real_a_real_b_3x3_full_rank() { - #[rustfmt::skip] - let a = array![ - [ 2.0, 1.0, 8.0], - [-2.0, 0.0, 3.0], - [ 7.0, 6.0, 5.0], - ]; - #[rustfmt::skip] - let b = array![ - [ 1.0, 2.0, -7.0], - [-3.0, 1.0, 6.0], - [ 4.0, -5.0, 1.0], - ]; - let (geneigvals, eigvecs) = (a.clone(), b.clone()).eig_generalized(None).unwrap(); - - let a = a.map(|v| v.as_c()); - let b = b.map(|v| v.as_c()); - for (ge, vec) in geneigvals.iter().zip(eigvecs.columns()) { - if let GeneralizedEigenvalue::Finite(e, _) = ge { - let ebv = b.dot(&vec).map(|v| v * e); - let av = a.dot(&vec); - assert_close_l2!(&av, &ebv, 1e-7); - } - } - - let mut eigvals = geneigvals - .iter() - .filter_map(|ge: &GeneralizedEigenvalue| match ge { - GeneralizedEigenvalue::Finite(e, _) => Some(e.clone()), - GeneralizedEigenvalue::Indeterminate(_) => None, - }) - .collect::>(); - eigvals.sort_by(|a, b| a.re().partial_cmp(&b.re()).unwrap()); - let eigvals = Array1::from_vec(eigvals); - // Reference eigenvalues from Mathematica - assert_close_l2!( - &eigvals, - &array![-0.4415795111, 0.5619249537, 50.87965456].map(c64::from), - 1e-7 - ); -} - -#[test] -fn real_a_real_b_3x3_nullity_1() { - #[rustfmt::skip] - let a = array![ - [ 2.0, 1.0, 8.0], - [-2.0, 0.0, 3.0], - [ 7.0, 6.0, 5.0], - ]; - #[rustfmt::skip] - let b = array![ - [1.0, 2.0, 3.0], - [0.0, 1.0, 1.0], - [1.0, -1.0, 0.0], - ]; - let (geneigvals, eigvecs) = (a.clone(), b.clone()).eig_generalized(Some(1e-4)).unwrap(); - - let a = a.map(|v| v.as_c()); - let b = b.map(|v| v.as_c()); - for (ge, vec) in geneigvals.iter().zip(eigvecs.columns()) { - if let GeneralizedEigenvalue::Finite(e, _) = ge { - let ebv = b.dot(&vec).map(|v| v * e); - let av = a.dot(&vec); - assert_close_l2!(&av, &ebv, 1e-7); - } - } - - let mut eigvals = geneigvals - .iter() - .filter_map(|ge: &GeneralizedEigenvalue| match ge { - GeneralizedEigenvalue::Finite(e, _) => Some(e.clone()), - GeneralizedEigenvalue::Indeterminate(_) => None, - }) - .collect::>(); - eigvals.sort_by(|a, b| a.re().partial_cmp(&b.re()).unwrap()); - let eigvals = Array1::from_vec(eigvals); - // Reference eigenvalues from Mathematica - assert_close_l2!( - &eigvals, - &array![-12.91130192, 3.911301921].map(c64::from), - 1e-7 - ); -} - -#[test] -fn complex_a_complex_b_3x3_full_rank() { - #[rustfmt::skip] - let a = array![ - [c64::new(1.0, 2.0), c64::new(-3.0, 0.5), c64::new( 0.0, -1.0)], - [c64::new(2.5, -4.0), c64::new( 1.0, 1.0), c64::new(-1.5, 2.5)], - [c64::new(0.0, 0.0), c64::new( 3.0, -2.0), c64::new( 4.0, 4.0)], - ]; - #[rustfmt::skip] - let b = array![ - [c64::new(-2.0, 1.0), c64::new( 3.5, -1.0), c64::new( 1.0, 1.0)], - [c64::new( 0.0, -3.0), c64::new( 2.0, 2.0), c64::new(-4.0, 0.0)], - [c64::new( 5.0, 5.0), c64::new(-1.5, 1.5), c64::new( 0.0, -2.0)], - ]; - let (geneigvals, eigvecs) = (a.clone(), b.clone()).eig_generalized(None).unwrap(); - - let a = a.map(|v| v.as_c()); - let b = b.map(|v| v.as_c()); - for (ge, vec) in geneigvals.iter().zip(eigvecs.columns()) { - if let GeneralizedEigenvalue::Finite(e, _) = ge { - let ebv = b.dot(&vec).map(|v| v * e); - let av = a.dot(&vec); - assert_close_l2!(&av, &ebv, 1e-7); - } - } - - let mut eigvals = geneigvals - .iter() - .filter_map(|ge: &GeneralizedEigenvalue| match ge { - GeneralizedEigenvalue::Finite(e, _) => Some(e.clone()), - GeneralizedEigenvalue::Indeterminate(_) => None, - }) - .collect::>(); - eigvals.sort_by(|a, b| a.re().partial_cmp(&b.re()).unwrap()); - let eigvals = Array1::from_vec(eigvals); - // Reference eigenvalues from Mathematica - assert_close_l2!( - &eigvals, - &array![ - c64::new(-0.701598, -1.71262), - c64::new(-0.67899, -0.0172468), - c64::new(0.59059, 0.276034) - ], - 1e-5 - ); -} - -#[test] -fn complex_a_complex_b_3x3_nullity_1() { - #[rustfmt::skip] - let a = array![ - [c64::new(1.0, 2.0), c64::new(-3.0, 0.5), c64::new( 0.0, -1.0)], - [c64::new(2.5, -4.0), c64::new( 1.0, 1.0), c64::new(-1.5, 2.5)], - [c64::new(0.0, 0.0), c64::new( 3.0, -2.0), c64::new( 4.0, 4.0)], - ]; - #[rustfmt::skip] - let b = array![ - [c64::new(-2.55604, -4.10176), c64::new(9.03944, 3.745000), c64::new(35.4641, 21.1704)], - [c64::new( 7.85029, 7.02144), c64::new(9.23225, -0.479451), c64::new(13.9507, -16.5402)], - [c64::new(-4.47803, 3.98981), c64::new(9.44434, -4.519970), c64::new(40.9006, -23.5060)], - ]; - let (geneigvals, eigvecs) = (a.clone(), b.clone()).eig_generalized(Some(1e-4)).unwrap(); - - let a = a.map(|v| v.as_c()); - let b = b.map(|v| v.as_c()); - for (ge, vec) in geneigvals.iter().zip(eigvecs.columns()) { - if let GeneralizedEigenvalue::Finite(e, _) = ge { - let ebv = b.dot(&vec).map(|v| v * e); - let av = a.dot(&vec); - assert_close_l2!(&av, &ebv, 1e-7); - } - } - - let mut eigvals = geneigvals - .iter() - .filter_map(|ge: &GeneralizedEigenvalue| match ge { - GeneralizedEigenvalue::Finite(e, _) => Some(e.clone()), - GeneralizedEigenvalue::Indeterminate(_) => None, - }) - .collect::>(); - eigvals.sort_by(|a, b| a.re().partial_cmp(&b.re()).unwrap()); - let eigvals = Array1::from_vec(eigvals); - // Reference eigenvalues from Mathematica - assert_close_l2!( - &eigvals, - &array![ - c64::new(-0.0620674, -0.270016), - c64::new(0.0218236, 0.0602709), - ], - 1e-5 - ); -} diff --git a/ndarray-linalg/tests/eigh.rs b/ndarray-linalg/tests/eigh.rs deleted file mode 100644 index 8d8ce385..00000000 --- a/ndarray-linalg/tests/eigh.rs +++ /dev/null @@ -1,134 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[should_panic] -#[test] -fn eigh_generalized_shape_mismatch() { - let a = Array2::::eye(3); - let b = Array2::::eye(2); - let _ = (a, b).eigh_inplace(UPLO::Upper); -} - -#[test] -fn fixed() { - let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]); - let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Upper).unwrap(); - assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7); - - // Check eigenvectors are orthogonalized - let s = vecs.t().dot(&vecs); - assert_close_l2!(&s, &Array::eye(3), 1.0e-7); - - for (i, v) in vecs.axis_iter(Axis(1)).enumerate() { - let av = a.dot(&v); - let ev = v.mapv(|x| e[i] * x); - assert_close_l2!(&av, &ev, 1.0e-7); - } -} - -#[test] -fn fixed_t() { - let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]).reversed_axes(); - let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Upper).unwrap(); - assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7); - - // Check eigenvectors are orthogonalized - let s = vecs.t().dot(&vecs); - assert_close_l2!(&s, &Array::eye(3), 1.0e-7); - - for (i, v) in vecs.axis_iter(Axis(1)).enumerate() { - let av = a.dot(&v); - let ev = v.mapv(|x| e[i] * x); - assert_close_l2!(&av, &ev, 1.0e-7); - } -} - -#[test] -fn fixed_lower() { - let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]); - let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Lower).unwrap(); - assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7); - - // Check eigenvectors are orthogonalized - let s = vecs.t().dot(&vecs); - assert_close_l2!(&s, &Array::eye(3), 1.0e-7); - - for (i, v) in vecs.axis_iter(Axis(1)).enumerate() { - let av = a.dot(&v); - let ev = v.mapv(|x| e[i] * x); - assert_close_l2!(&av, &ev, 1.0e-7); - } -} - -#[test] -fn fixed_t_lower() { - let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]).reversed_axes(); - let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Lower).unwrap(); - assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7); - - // Check eigenvectors are orthogonalized - let s = vecs.t().dot(&vecs); - assert_close_l2!(&s, &Array::eye(3), 1.0e-7); - - for (i, v) in vecs.axis_iter(Axis(1)).enumerate() { - let av = a.dot(&v); - let ev = v.mapv(|x| e[i] * x); - assert_close_l2!(&av, &ev, 1.0e-7); - } -} - -#[test] -fn ssqrt() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng); - let ans = a.clone(); - let s = a.ssqrt(UPLO::Upper).unwrap(); - println!("a = {:?}", &ans); - println!("s = {:?}", &s); - assert_close_l2!(&s.t(), &s, 1e-7); - let ss = s.dot(&s); - println!("ss = {:?}", &ss); - assert_close_l2!(&ss, &ans, 1e-7); -} - -#[test] -fn ssqrt_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng).reversed_axes(); - let ans = a.clone(); - let s = a.ssqrt(UPLO::Upper).unwrap(); - println!("a = {:?}", &ans); - println!("s = {:?}", &s); - assert_close_l2!(&s.t(), &s, 1e-7); - let ss = s.dot(&s); - println!("ss = {:?}", &ss); - assert_close_l2!(&ss, &ans, 1e-7); -} - -#[test] -fn ssqrt_lower() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng); - let ans = a.clone(); - let s = a.ssqrt(UPLO::Lower).unwrap(); - println!("a = {:?}", &ans); - println!("s = {:?}", &s); - assert_close_l2!(&s.t(), &s, 1e-7); - let ss = s.dot(&s); - println!("ss = {:?}", &ss); - assert_close_l2!(&ss, &ans, 1e-7); -} - -#[test] -fn ssqrt_t_lower() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng).reversed_axes(); - let ans = a.clone(); - let s = a.ssqrt(UPLO::Lower).unwrap(); - println!("a = {:?}", &ans); - println!("s = {:?}", &s); - assert_close_l2!(&s.t(), &s, 1e-7); - let ss = s.dot(&s); - println!("ss = {:?}", &ss); - assert_close_l2!(&ss, &ans, 1e-7); -} diff --git a/ndarray-linalg/tests/householder.rs b/ndarray-linalg/tests/householder.rs deleted file mode 100644 index 83b500f7..00000000 --- a/ndarray-linalg/tests/householder.rs +++ /dev/null @@ -1,99 +0,0 @@ -use ndarray::*; -use ndarray_linalg::{krylov::*, *}; - -fn over(rtol: A::Real) { - const N: usize = 4; - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((N, N * 2), &mut rng); - - // Terminate - let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); - let a_sub = a.slice(s![.., 0..N]); - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol; "Check Q^H Q = I"); - assert_close_l2!(&q.dot(&r), &a_sub, rtol; "Check A = QR"); - - // Skip - let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Skip); - let a_sub = a.slice(s![.., 0..N]); - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol); - assert_close_l2!(&q.dot(&r), &a_sub, rtol); - - // Full - let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Full); - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol); - assert_close_l2!(&q.dot(&r), &a, rtol); -} - -#[test] -fn over_f32() { - over::(1e-5); -} -#[test] -fn over_f64() { - over::(1e-9); -} -#[test] -fn over_c32() { - over::(1e-5); -} -#[test] -fn over_c64() { - over::(1e-9); -} - -fn full(rtol: A::Real) { - const N: usize = 5; - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((N, N), &mut rng); - let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol; "Check Q^H Q = I"); - assert_close_l2!(&q.dot(&r), &a, rtol; "Check A = QR"); -} - -#[test] -fn full_f32() { - full::(1e-5); -} -#[test] -fn full_f64() { - full::(1e-9); -} -#[test] -fn full_c32() { - full::(1e-5); -} -#[test] -fn full_c64() { - full::(1e-9); -} - -fn half(rtol: A::Real) { - const N: usize = 4; - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((N, N / 2), &mut rng); - let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N / 2), rtol; "Check Q^H Q = I"); - assert_close_l2!(&q.dot(&r), &a, rtol; "Check A = QR"); -} - -#[test] -fn half_f32() { - half::(1e-5); -} -#[test] -fn half_f64() { - half::(1e-9); -} -#[test] -fn half_c32() { - half::(1e-5); -} -#[test] -fn half_c64() { - half::(1e-9); -} diff --git a/ndarray-linalg/tests/inner.rs b/ndarray-linalg/tests/inner.rs deleted file mode 100644 index 076b2791..00000000 --- a/ndarray-linalg/tests/inner.rs +++ /dev/null @@ -1,27 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[should_panic] -#[test] -fn size_shoter() { - let a: Array1 = Array::zeros(3); - let b = Array::zeros(4); - a.inner(&b); -} - -#[should_panic] -#[test] -fn size_longer() { - let a: Array1 = Array::zeros(3); - let b = Array::zeros(4); - b.inner(&a); -} - -#[test] -fn abs() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array1 = random_using(1, &mut rng); - let aa = a.inner(&a); - assert_aclose!(aa.re(), a.norm().powi(2), 1e-5); - assert_aclose!(aa.im(), 0.0, 1e-5); -} diff --git a/ndarray-linalg/tests/inv.rs b/ndarray-linalg/tests/inv.rs deleted file mode 100644 index 93ff1aad..00000000 --- a/ndarray-linalg/tests/inv.rs +++ /dev/null @@ -1,123 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -fn test_inv_random(n: usize, set_f: bool, rtol: A::Real) -where - A: Scalar + Lapack, -{ - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using([n; 2].set_f(set_f), &mut rng); - let identity = Array2::eye(n); - assert_close_l2!(&a.inv().unwrap().dot(&a), &identity, rtol); - assert_close_l2!( - &a.factorize().unwrap().inv().unwrap().dot(&a), - &identity, - rtol - ); - assert_close_l2!( - &a.clone().factorize_into().unwrap().inv().unwrap().dot(&a), - &identity, - rtol - ); -} - -fn test_inv_into_random(n: usize, set_f: bool, rtol: A::Real) -where - A: Scalar + Lapack, -{ - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using([n; 2].set_f(set_f), &mut rng); - let identity = Array2::eye(n); - assert_close_l2!(&a.clone().inv_into().unwrap().dot(&a), &identity, rtol); - assert_close_l2!( - &a.factorize().unwrap().inv_into().unwrap().dot(&a), - &identity, - rtol - ); - assert_close_l2!( - &a.clone() - .factorize_into() - .unwrap() - .inv_into() - .unwrap() - .dot(&a), - &identity, - rtol - ); -} - -#[test] -fn inv_empty() { - test_inv_random::(0, false, 0.); - test_inv_random::(0, false, 0.); - test_inv_random::(0, false, 0.); - test_inv_random::(0, false, 0.); -} - -#[test] -fn inv_random_float() { - for n in 1..=8 { - for &set_f in &[false, true] { - test_inv_random::(n, set_f, 1e-3); - test_inv_random::(n, set_f, 1e-9); - } - } -} - -#[test] -fn inv_random_complex() { - for n in 1..=8 { - for &set_f in &[false, true] { - test_inv_random::(n, set_f, 1e-3); - test_inv_random::(n, set_f, 1e-9); - } - } -} - -#[test] -fn inv_into_empty() { - test_inv_into_random::(0, false, 0.); - test_inv_into_random::(0, false, 0.); - test_inv_into_random::(0, false, 0.); - test_inv_into_random::(0, false, 0.); -} - -#[test] -fn inv_into_random_float() { - for n in 1..=8 { - for &set_f in &[false, true] { - test_inv_into_random::(n, set_f, 1e-3); - test_inv_into_random::(n, set_f, 1e-9); - } - } -} - -#[test] -fn inv_into_random_complex() { - for n in 1..=8 { - for &set_f in &[false, true] { - test_inv_into_random::(n, set_f, 1e-3); - test_inv_into_random::(n, set_f, 1e-9); - } - } -} - -#[test] -#[should_panic] -fn inv_error() { - // do not have inverse - let a = Array::::zeros(9) - .into_shape_with_order((3, 3)) - .unwrap(); - let a_inv = a.inv().unwrap(); - println!("{:?}", a_inv); -} - -#[test] -fn inv_2x2() { - // Related to issue #123 where this problem led to a wrongly computed inverse when using the - // `openblas` backend. - let a: Array2 = array!([1.0, 2.0], [3.0, 4.0]); - let a_inv = a.inv().unwrap(); - assert_close_l2!(&a_inv, &array!([-2.0, 1.0], [1.5, -0.5]), 1e-7); -} diff --git a/ndarray-linalg/tests/layout.rs b/ndarray-linalg/tests/layout.rs deleted file mode 100644 index 2c253f5e..00000000 --- a/ndarray-linalg/tests/layout.rs +++ /dev/null @@ -1,31 +0,0 @@ -use ndarray::*; -use ndarray_linalg::layout::MatrixLayout; -use ndarray_linalg::*; - -#[test] -fn layout_c_3x1() { - let a: Array2 = Array::zeros((3, 1)); - println!("a = {:?}", &a); - assert_eq!(a.layout().unwrap(), MatrixLayout::C { row: 3, lda: 1 }); -} - -#[test] -fn layout_f_3x1() { - let a: Array2 = Array::zeros((3, 1).f()); - println!("a = {:?}", &a); - assert_eq!(a.layout().unwrap(), MatrixLayout::F { col: 1, lda: 3 }); -} - -#[test] -fn layout_c_3x2() { - let a: Array2 = Array::zeros((3, 2)); - println!("a = {:?}", &a); - assert_eq!(a.layout().unwrap(), MatrixLayout::C { row: 3, lda: 2 }); -} - -#[test] -fn layout_f_3x2() { - let a: Array2 = Array::zeros((3, 2).f()); - println!("a = {:?}", &a); - assert_eq!(a.layout().unwrap(), MatrixLayout::F { col: 2, lda: 3 }); -} diff --git a/ndarray-linalg/tests/least_squares.rs b/ndarray-linalg/tests/least_squares.rs deleted file mode 100644 index 17f62b64..00000000 --- a/ndarray-linalg/tests/least_squares.rs +++ /dev/null @@ -1,138 +0,0 @@ -/// Solve least square problem `|b - Ax|` -use approx::AbsDiffEq; -use ndarray::*; -use ndarray_linalg::*; - -/// A is square. `x = A^{-1} b`, `|b - Ax| = 0` -fn test_exact(a: Array2) { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array1 = random_using(3, &mut rng); - let result = a.least_squares(&b).unwrap(); - // unpack result - let x = result.solution; - let residual_l2_square = result.residual_sum_of_squares.unwrap()[()]; - - // must be full-rank - assert_eq!(result.rank, 3); - - // |b - Ax| == 0 - assert!(residual_l2_square < T::real(1.0e-4)); - - // b == Ax - let ax = a.dot(&x); - assert_close_max!(&b, &ax, T::real(1.0e-4)); -} - -macro_rules! impl_exact { - ($scalar:ty) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 3), &mut rng); - test_exact(a) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 3).f(), &mut rng); - test_exact(a) - } - } - }; -} - -impl_exact!(f32); -impl_exact!(f64); -impl_exact!(c32); -impl_exact!(c64); - -/// #column < #row case. -/// Linear problem is overdetermined, `|b - Ax| > 0`. -fn test_overdetermined(a: Array2) -where - T::Real: AbsDiffEq, -{ - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array1 = random_using(4, &mut rng); - let result = a.least_squares(&b).unwrap(); - // unpack result - let x = result.solution; - let residual_l2_square = result.residual_sum_of_squares.unwrap()[()]; - - // Must be full-rank - assert_eq!(result.rank, 3); - - // eval `residual = b - Ax` - let residual = &b - &a.dot(&x); - assert!(residual_l2_square.abs_diff_eq(&residual.norm_l2().powi(2), T::real(1.0e-4))); - - // `|residual| < |b|` - assert!(residual.norm_l2() < b.norm_l2()); -} - -macro_rules! impl_overdetermined { - ($scalar:ty) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((4, 3), &mut rng); - test_overdetermined(a) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((4, 3).f(), &mut rng); - test_overdetermined(a) - } - } - }; -} - -impl_overdetermined!(f32); -impl_overdetermined!(f64); -impl_overdetermined!(c32); -impl_overdetermined!(c64); - -/// #column > #row case. -/// Linear problem is underdetermined, `|b - Ax| = 0` and `x` is not unique -fn test_underdetermined(a: Array2) { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array1 = random_using(3, &mut rng); - let result = a.least_squares(&b).unwrap(); - assert_eq!(result.rank, 3); - assert!(result.residual_sum_of_squares.is_none()); - - // b == Ax - let x = result.solution; - let ax = a.dot(&x); - assert_close_max!(&b, &ax, T::real(1.0e-4)); -} - -macro_rules! impl_underdetermined { - ($scalar:ty) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 4), &mut rng); - test_underdetermined(a) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 4).f(), &mut rng); - test_underdetermined(a) - } - } - }; -} - -impl_underdetermined!(f32); -impl_underdetermined!(f64); -impl_underdetermined!(c32); -impl_underdetermined!(c64); diff --git a/ndarray-linalg/tests/least_squares_nrhs.rs b/ndarray-linalg/tests/least_squares_nrhs.rs deleted file mode 100644 index bcf6d013..00000000 --- a/ndarray-linalg/tests/least_squares_nrhs.rs +++ /dev/null @@ -1,202 +0,0 @@ -/// Solve least square problem `|b - Ax|` with multi-column `b` -use approx::AbsDiffEq; -use ndarray::*; -use ndarray_linalg::*; - -/// A is square. `x = A^{-1} b`, `|b - Ax| = 0` -fn test_exact(a: Array2, b: Array2) { - assert_eq!(a.layout().unwrap().size(), (3, 3)); - assert_eq!(b.layout().unwrap().size(), (3, 2)); - - let result = a.least_squares(&b).unwrap(); - dbg!(&result); - // unpack result - let x: Array2 = result.solution; - let residual_l2_square: Array1 = result.residual_sum_of_squares.unwrap(); - - // must be full-rank - assert_eq!(result.rank, 3); - - // |b - Ax| == 0 - for &residual in &residual_l2_square { - assert!(residual < T::real(1.0e-4)); - } - - // b == Ax - let ax = a.dot(&x); - assert_close_l2!(&b, &ax, T::real(1.0e-4)); -} - -macro_rules! impl_exact { - ($scalar:ty) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 3), &mut rng); - let b: Array2<$scalar> = random_using((3, 2), &mut rng); - test_exact(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 3), &mut rng); - let b: Array2<$scalar> = random_using((3, 2).f(), &mut rng); - test_exact(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 3).f(), &mut rng); - let b: Array2<$scalar> = random_using((3, 2), &mut rng); - test_exact(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 3).f(), &mut rng); - let b: Array2<$scalar> = random_using((3, 2).f(), &mut rng); - test_exact(a, b) - } - } - }; -} - -impl_exact!(f32); -impl_exact!(f64); -impl_exact!(c32); -impl_exact!(c64); - -/// #column < #row case. -/// Linear problem is overdetermined, `|b - Ax| > 0`. -fn test_overdetermined(a: Array2, bs: Array2) -where - T::Real: AbsDiffEq, -{ - assert_eq!(a.layout().unwrap().size(), (4, 3)); - assert_eq!(bs.layout().unwrap().size(), (4, 2)); - - let result = a.least_squares(&bs).unwrap(); - // unpack result - let xs = result.solution; - let residual_l2_square = result.residual_sum_of_squares.unwrap(); - - // Must be full-rank - assert_eq!(result.rank, 3); - - for j in 0..2 { - let b = bs.index_axis(Axis(1), j); - let x = xs.index_axis(Axis(1), j); - let residual = &b - &a.dot(&x); - let residual_l2_sq = residual_l2_square[j]; - assert!(residual_l2_sq.abs_diff_eq(&residual.norm_l2().powi(2), T::real(1.0e-4))); - - // `|residual| < |b|` - assert!(residual.norm_l2() < b.norm_l2()); - } -} - -macro_rules! impl_overdetermined { - ($scalar:ty) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((4, 3), &mut rng); - let b: Array2<$scalar> = random_using((4, 2), &mut rng); - test_overdetermined(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((4, 3).f(), &mut rng); - let b: Array2<$scalar> = random_using((4, 2), &mut rng); - test_overdetermined(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((4, 3), &mut rng); - let b: Array2<$scalar> = random_using((4, 2).f(), &mut rng); - test_overdetermined(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((4, 3).f(), &mut rng); - let b: Array2<$scalar> = random_using((4, 2).f(), &mut rng); - test_overdetermined(a, b) - } - } - }; -} - -impl_overdetermined!(f32); -impl_overdetermined!(f64); -impl_overdetermined!(c32); -impl_overdetermined!(c64); - -/// #column > #row case. -/// Linear problem is underdetermined, `|b - Ax| = 0` and `x` is not unique -fn test_underdetermined(a: Array2, b: Array2) { - assert_eq!(a.layout().unwrap().size(), (3, 4)); - assert_eq!(b.layout().unwrap().size(), (3, 2)); - - let result = a.least_squares(&b).unwrap(); - assert_eq!(result.rank, 3); - assert!(result.residual_sum_of_squares.is_none()); - - // b == Ax - let x = result.solution; - let ax = a.dot(&x); - assert_close_l2!(&b, &ax, T::real(1.0e-4)); -} - -macro_rules! impl_underdetermined { - ($scalar:ty) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 4), &mut rng); - let b: Array2<$scalar> = random_using((3, 2), &mut rng); - test_underdetermined(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 4).f(), &mut rng); - let b: Array2<$scalar> = random_using((3, 2), &mut rng); - test_underdetermined(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 4), &mut rng); - let b: Array2<$scalar> = random_using((3, 2).f(), &mut rng); - test_underdetermined(a, b) - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$scalar> = random_using((3, 4).f(), &mut rng); - let b: Array2<$scalar> = random_using((3, 2).f(), &mut rng); - test_underdetermined(a, b) - } - } - }; -} - -impl_underdetermined!(f32); -impl_underdetermined!(f64); -impl_underdetermined!(c32); -impl_underdetermined!(c64); diff --git a/ndarray-linalg/tests/mgs.rs b/ndarray-linalg/tests/mgs.rs deleted file mode 100644 index 9e9aa29e..00000000 --- a/ndarray-linalg/tests/mgs.rs +++ /dev/null @@ -1,86 +0,0 @@ -use ndarray::*; -use ndarray_linalg::{krylov::*, *}; - -fn qr_full() { - const N: usize = 5; - let rtol: A::Real = A::real(1e-9); - - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((N, N), &mut rng); - let (q, r) = mgs(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); - assert_close_l2!(&q.dot(&r), &a, rtol); - - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol); -} - -#[test] -fn qr_full_real() { - qr_full::(); -} - -#[test] -fn qr_full_complex() { - qr_full::(); -} - -fn qr() { - const N: usize = 4; - let rtol: A::Real = A::real(1e-9); - - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((N, N / 2), &mut rng); - let (q, r) = mgs(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); - assert_close_l2!(&q.dot(&r), &a, rtol); - - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N / 2), rtol); -} - -#[test] -fn qr_real() { - qr::(); -} - -#[test] -fn qr_complex() { - qr::(); -} - -fn qr_over() { - const N: usize = 4; - let rtol: A::Real = A::real(1e-9); - - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((N, N * 2), &mut rng); - - // Terminate - let (q, r) = mgs(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); - let a_sub = a.slice(s![.., 0..N]); - assert_close_l2!(&q.dot(&r), &a_sub, rtol); - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol); - - // Skip - let (q, r) = mgs(a.axis_iter(Axis(1)), N, rtol, Strategy::Skip); - let a_sub = a.slice(s![.., 0..N]); - assert_close_l2!(&q.dot(&r), &a_sub, rtol); - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol); - - // Full - let (q, r) = mgs(a.axis_iter(Axis(1)), N, rtol, Strategy::Full); - assert_close_l2!(&q.dot(&r), &a, rtol); - let qc: Array2 = conjugate(&q); - assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol); -} - -#[test] -fn qr_over_real() { - qr_over::(); -} - -#[test] -fn qr_over_complex() { - qr_over::(); -} diff --git a/ndarray-linalg/tests/normalize.rs b/ndarray-linalg/tests/normalize.rs deleted file mode 100644 index 8d71a009..00000000 --- a/ndarray-linalg/tests/normalize.rs +++ /dev/null @@ -1,18 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[test] -fn n_columns() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((3, 2), &mut rng); - let (n, v) = normalize(a.clone(), NormalizeAxis::Column); - assert_close_l2!(&n.dot(&from_diag(&v)), &a, 1e-7); -} - -#[test] -fn n_rows() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((3, 2), &mut rng); - let (n, v) = normalize(a.clone(), NormalizeAxis::Row); - assert_close_l2!(&from_diag(&v).dot(&n), &a, 1e-7); -} diff --git a/ndarray-linalg/tests/opnorm.rs b/ndarray-linalg/tests/opnorm.rs deleted file mode 100644 index cd45d258..00000000 --- a/ndarray-linalg/tests/opnorm.rs +++ /dev/null @@ -1,55 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -fn test(a: Array2, one: f64, inf: f64, fro: f64) { - println!("ONE = {:?}", a.opnorm_one()); - println!("INF = {:?}", a.opnorm_inf()); - println!("FRO = {:?}", a.opnorm_fro()); - assert_rclose!(a.opnorm_one().unwrap(), one, 1e-7; "One norm"); - assert_rclose!(a.opnorm_inf().unwrap(), inf, 1e-7; "Infinity norm"); - assert_rclose!(a.opnorm_fro().unwrap(), fro, 1e-7; "Frobenius norm"); -} - -fn gen(i: usize, j: usize, rev: bool) -> Array2 { - let n = (i * j + 1) as f64; - if rev { - Array::range(1., n, 1.) - .into_shape_with_order((j, i)) - .unwrap() - .reversed_axes() - } else { - Array::range(1., n, 1.) - .into_shape_with_order((i, j)) - .unwrap() - } -} - -#[test] -fn opnorm_square() { - test(gen(3, 3, false), 18.0, 24.0, 285.0.sqrt()); -} - -#[test] -fn opnorm_square_t() { - test(gen(3, 3, true), 24.0, 18.0, 285.0.sqrt()); -} - -#[test] -fn opnorm_3x4() { - test(gen(3, 4, false), 24.0, 42.0, 650.0.sqrt()); -} - -#[test] -fn opnorm_3x4_t() { - test(gen(3, 4, true), 33.0, 30.0, 650.0.sqrt()); -} - -#[test] -fn opnorm_4x3() { - test(gen(4, 3, false), 30.0, 33.0, 650.0.sqrt()); -} - -#[test] -fn opnorm_4x3_t() { - test(gen(4, 3, true), 42.0, 24.0, 650.0.sqrt()); -} diff --git a/ndarray-linalg/tests/qr.rs b/ndarray-linalg/tests/qr.rs deleted file mode 100644 index 702ed060..00000000 --- a/ndarray-linalg/tests/qr.rs +++ /dev/null @@ -1,81 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; -use std::cmp::min; - -fn test(a: &Array2, n: usize, m: usize) { - let ans = a.clone(); - println!("a = \n{:?}", a); - let (q, r): (Array2<_>, Array2<_>) = a.qr().unwrap(); - println!("q = \n{:?}", &q); - println!("r = \n{:?}", &r); - assert_close_l2!(&q.t().dot(&q), &Array::eye(min(n, m)), 1e-7); - assert_close_l2!(&q.dot(&r), &ans, 1e-7); - assert_close_l2!(&r.clone().into_triangular(UPLO::Upper), &r, 1e-7); -} - -fn test_square(a: &Array2, n: usize, m: usize) { - let ans = a.clone(); - println!("a = \n{:?}", a); - let (q, r): (Array2<_>, Array2<_>) = a.qr_square().unwrap(); - println!("q = \n{:?}", &q); - println!("r = \n{:?}", &r); - assert_close_l2!(&q.t().dot(&q), &Array::eye(min(n, m)), 1e-7); - assert_close_l2!(&q.dot(&r), &ans, 1e-7); - assert_close_l2!(&r.clone().into_triangular(UPLO::Upper), &r, 1e-7); -} - -#[test] -fn qr_sq() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using((3, 3), &mut rng); - test_square(&a, 3, 3); -} - -#[test] -fn qr_sq_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using((3, 3).f(), &mut rng); - test_square(&a, 3, 3); -} - -#[test] -fn qr_3x3() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using((3, 3), &mut rng); - test(&a, 3, 3); -} - -#[test] -fn qr_3x3_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using((3, 3).f(), &mut rng); - test(&a, 3, 3); -} - -#[test] -fn qr_3x4() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using((3, 4), &mut rng); - test(&a, 3, 4); -} - -#[test] -fn qr_3x4_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using((3, 4).f(), &mut rng); - test(&a, 3, 4); -} - -#[test] -fn qr_4x3() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using((4, 3), &mut rng); - test(&a, 4, 3); -} - -#[test] -fn qr_4x3_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using((4, 3).f(), &mut rng); - test(&a, 4, 3); -} diff --git a/ndarray-linalg/tests/solve.rs b/ndarray-linalg/tests/solve.rs deleted file mode 100644 index 074350ce..00000000 --- a/ndarray-linalg/tests/solve.rs +++ /dev/null @@ -1,282 +0,0 @@ -use ndarray::prelude::*; -use ndarray_linalg::{ - assert_aclose, assert_close_l2, c32, c64, random_hpd_using, random_using, solve::*, - OperationNorm, Scalar, -}; - -macro_rules! test_solve { - ( - [$($elem_type:ty => $rtol:expr),*], - $a_ident:ident = $a:expr, - $x_ident:ident = $x:expr, - b = $b:expr, - $solve:ident, - ) => { - $({ - let $a_ident: Array2<$elem_type> = $a; - let $x_ident: Array1<$elem_type> = $x; - let b: Array1<$elem_type> = $b; - let a = $a_ident; - let x = $x_ident; - let rtol = $rtol; - assert_close_l2!(&a.$solve(&b).unwrap(), &x, rtol); - assert_close_l2!(&a.factorize().unwrap().$solve(&b).unwrap(), &x, rtol); - assert_close_l2!(&a.factorize_into().unwrap().$solve(&b).unwrap(), &x, rtol); - })* - }; -} - -macro_rules! test_solve_into { - ( - [$($elem_type:ty => $rtol:expr),*], - $a_ident:ident = $a:expr, - $x_ident:ident = $x:expr, - b = $b:expr, - $solve_into:ident, - ) => { - $({ - let $a_ident: Array2<$elem_type> = $a; - let $x_ident: Array1<$elem_type> = $x; - let b: Array1<$elem_type> = $b; - let a = $a_ident; - let x = $x_ident; - let rtol = $rtol; - assert_close_l2!(&a.$solve_into(b.clone()).unwrap(), &x, rtol); - assert_close_l2!(&a.factorize().unwrap().$solve_into(b.clone()).unwrap(), &x, rtol); - assert_close_l2!(&a.factorize_into().unwrap().$solve_into(b.clone()).unwrap(), &x, rtol); - })* - }; -} - -macro_rules! test_solve_inplace { - ( - [$($elem_type:ty => $rtol:expr),*], - $a_ident:ident = $a:expr, - $x_ident:ident = $x:expr, - b = $b:expr, - $solve_inplace:ident, - ) => { - $({ - let $a_ident: Array2<$elem_type> = $a; - let $x_ident: Array1<$elem_type> = $x; - let b: Array1<$elem_type> = $b; - let a = $a_ident; - let x = $x_ident; - let rtol = $rtol; - { - let mut b = b.clone(); - assert_close_l2!(&a.$solve_inplace(&mut b).unwrap(), &x, rtol); - assert_close_l2!(&b, &x, rtol); - } - { - let mut b = b.clone(); - assert_close_l2!(&a.factorize().unwrap().$solve_inplace(&mut b).unwrap(), &x, rtol); - assert_close_l2!(&b, &x, rtol); - } - { - let mut b = b.clone(); - assert_close_l2!(&a.factorize_into().unwrap().$solve_inplace(&mut b).unwrap(), &x, rtol); - assert_close_l2!(&b, &x, rtol); - } - })* - }; -} - -macro_rules! test_solve_all { - ( - [$($elem_type:ty => $rtol:expr),*], - $a_ident:ident = $a:expr, - $x_ident:ident = $x:expr, - b = $b:expr, - [$solve:ident, $solve_into:ident, $solve_inplace:ident], - ) => { - test_solve!([$($elem_type => $rtol),*], $a_ident = $a, $x_ident = $x, b = $b, $solve,); - test_solve_into!([$($elem_type => $rtol),*], $a_ident = $a, $x_ident = $x, b = $b, $solve_into,); - test_solve_inplace!([$($elem_type => $rtol),*], $a_ident = $a, $x_ident = $x, b = $b, $solve_inplace,); - }; -} - -#[test] -fn solve_random_float() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - for n in 0..=8 { - for &set_f in &[false, true] { - test_solve_all!( - [f32 => 1e-3, f64 => 1e-9], - a = random_using([n; 2].set_f(set_f), &mut rng), - x = random_using(n, &mut rng), - b = a.dot(&x), - [solve, solve_into, solve_inplace], - ); - } - } -} - -#[test] -fn solve_random_complex() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - for n in 0..=8 { - for &set_f in &[false, true] { - test_solve_all!( - [c32 => 1e-3, c64 => 1e-9], - a = random_using([n; 2].set_f(set_f), &mut rng), - x = random_using(n, &mut rng), - b = a.dot(&x), - [solve, solve_into, solve_inplace], - ); - } - } -} - -#[should_panic] -#[test] -fn solve_shape_mismatch() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((3, 3), &mut rng); - let b: Array1 = random_using(2, &mut rng); - let _ = a.solve_into(b); -} - -#[test] -fn solve_t_random_float() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - for n in 0..=8 { - for &set_f in &[false, true] { - test_solve_all!( - [f32 => 1e-3, f64 => 1e-9], - a = random_using([n; 2].set_f(set_f), &mut rng), - x = random_using(n, &mut rng), - b = a.t().dot(&x), - [solve_t, solve_t_into, solve_t_inplace], - ); - } - } -} - -#[should_panic] -#[test] -fn solve_t_shape_mismatch() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((3, 3).f(), &mut rng); - let b: Array1 = random_using(4, &mut rng); - let _ = a.solve_into(b); -} - -#[test] -fn solve_t_random_complex() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - for n in 0..=8 { - for &set_f in &[false, true] { - test_solve_all!( - [c32 => 1e-3, c64 => 1e-9], - a = random_using([n; 2].set_f(set_f), &mut rng), - x = random_using(n, &mut rng), - b = a.t().dot(&x), - [solve_t, solve_t_into, solve_t_inplace], - ); - } - } -} - -#[should_panic] -#[test] -fn solve_factorized_shape_mismatch() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((3, 3), &mut rng); - let b: Array1 = random_using(4, &mut rng); - let f = a.factorize_into().unwrap(); - let _ = f.solve_into(b); -} - -#[test] -fn solve_h_random_float() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - for n in 0..=8 { - for &set_f in &[false, true] { - test_solve_all!( - [f32 => 1e-3, f64 => 1e-9], - a = random_using([n; 2].set_f(set_f), &mut rng), - x = random_using(n, &mut rng), - b = a.t().mapv(|x| x.conj()).dot(&x), - [solve_h, solve_h_into, solve_h_inplace], - ); - } - } -} - -#[should_panic] -#[test] -fn solve_factorized_t_shape_mismatch() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((3, 3).f(), &mut rng); - let b: Array1 = random_using(4, &mut rng); - let f = a.factorize_into().unwrap(); - let _ = f.solve_into(b); -} - -#[test] -fn solve_h_random_complex() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - for n in 0..=8 { - for &set_f in &[false, true] { - test_solve_all!( - [c32 => 1e-3, c64 => 1e-9], - a = random_using([n; 2].set_f(set_f), &mut rng), - x = random_using(n, &mut rng), - b = a.t().mapv(|x| x.conj()).dot(&x), - [solve_h, solve_h_into, solve_h_inplace], - ); - } - } -} - -#[test] -fn rcond() { - macro_rules! rcond { - ($elem:ty, $rows:expr, $atol:expr) => { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2<$elem> = random_hpd_using($rows, &mut rng); - let rcond = 1. / (a.opnorm_one().unwrap() * a.inv().unwrap().opnorm_one().unwrap()); - assert_aclose!(a.rcond().unwrap(), rcond, $atol); - assert_aclose!(a.rcond_into().unwrap(), rcond, $atol); - }; - } - for rows in 1..6 { - rcond!(f64, rows, 0.2); - rcond!(f32, rows, 0.5); - rcond!(c64, rows, 0.2); - rcond!(c32, rows, 0.5); - } -} - -#[test] -fn rcond_hilbert() { - macro_rules! rcond_hilbert { - ($elem:ty, $rows:expr, $atol:expr) => { - let a = Array2::<$elem>::from_shape_fn(($rows, $rows), |(i, j)| { - 1. / (i as $elem + j as $elem + 1.) - }); - assert_aclose!(a.rcond().unwrap(), 0., $atol); - assert_aclose!(a.rcond_into().unwrap(), 0., $atol); - }; - } - rcond_hilbert!(f64, 10, 1e-9); - rcond_hilbert!(f32, 10, 1e-3); -} - -#[test] -fn rcond_identity() { - macro_rules! rcond_identity { - ($elem:ty, $rows:expr, $atol:expr) => { - let a = Array2::<$elem>::eye($rows); - assert_aclose!(a.rcond().unwrap(), 1., $atol); - assert_aclose!(a.rcond_into().unwrap(), 1., $atol); - }; - } - for rows in 1..6 { - rcond_identity!(f64, rows, 1e-9); - rcond_identity!(f32, rows, 1e-3); - rcond_identity!(c64, rows, 1e-9); - rcond_identity!(c32, rows, 1e-3); - } -} diff --git a/ndarray-linalg/tests/solveh.rs b/ndarray-linalg/tests/solveh.rs deleted file mode 100644 index 25513551..00000000 --- a/ndarray-linalg/tests/solveh.rs +++ /dev/null @@ -1,70 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[should_panic] -#[test] -fn solveh_shape_mismatch() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng); - let b: Array1 = random_using(2, &mut rng); - let _ = a.solveh_into(b); -} - -#[should_panic] -#[test] -fn factorizeh_solveh_shape_mismatch() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng); - let b: Array1 = random_using(2, &mut rng); - let f = a.factorizeh_into().unwrap(); - let _ = f.solveh_into(b); -} - -#[test] -fn solveh_random() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng); - let x: Array1 = random_using(3, &mut rng); - let b = a.dot(&x); - let y = a.solveh_into(b).unwrap(); - assert_close_l2!(&x, &y, 1e-7); - - let b = a.dot(&x); - let f = a.factorizeh_into().unwrap(); - let y = f.solveh_into(b).unwrap(); - assert_close_l2!(&x, &y, 1e-7); -} - -#[should_panic] -#[test] -fn solveh_t_shape_mismatch() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng).reversed_axes(); - let b: Array1 = random_using(2, &mut rng); - let _ = a.solveh_into(b); -} - -#[should_panic] -#[test] -fn factorizeh_solveh_t_shape_mismatch() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng).reversed_axes(); - let b: Array1 = random_using(2, &mut rng); - let f = a.factorizeh_into().unwrap(); - let _ = f.solveh_into(b); -} - -#[test] -fn solveh_random_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_hpd_using(3, &mut rng).reversed_axes(); - let x: Array1 = random_using(3, &mut rng); - let b = a.dot(&x); - let y = a.solveh_into(b).unwrap(); - assert_close_l2!(&x, &y, 1e-7); - - let b = a.dot(&x); - let f = a.factorizeh_into().unwrap(); - let y = f.solveh_into(b).unwrap(); - assert_close_l2!(&x, &y, 1e-7); -} diff --git a/ndarray-linalg/tests/svd.rs b/ndarray-linalg/tests/svd.rs deleted file mode 100644 index 0eac35ea..00000000 --- a/ndarray-linalg/tests/svd.rs +++ /dev/null @@ -1,94 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; -use std::cmp::min; - -fn test(a: &Array2) { - let (n, m) = a.dim(); - let answer = a.clone(); - println!("a = \n{:?}", a); - let (u, s, vt): (_, Array1<_>, _) = a.svd(true, true).unwrap(); - let u: Array2<_> = u.unwrap(); - let vt: Array2<_> = vt.unwrap(); - println!("u = \n{:?}", &u); - println!("s = \n{:?}", &s); - println!("v = \n{:?}", &vt); - let mut sm = Array::::zeros((n, m)); - for i in 0..min(n, m) { - sm[(i, i)] = T::from(s[i]).unwrap(); - } - assert_close_l2!(&u.dot(&sm).dot(&vt), &answer, T::real(1e-7)); -} - -fn test_no_vt(a: &Array2) { - let (n, _m) = a.dim(); - println!("a = \n{:?}", a); - let (u, _s, vt): (_, Array1<_>, _) = a.svd(true, false).unwrap(); - assert!(u.is_some()); - assert!(vt.is_none()); - let u = u.unwrap(); - assert_eq!(u.dim().0, n); - assert_eq!(u.dim().1, n); -} - -fn test_no_u(a: &Array2) { - let (_n, m) = a.dim(); - println!("a = \n{:?}", a); - let (u, _s, vt): (_, Array1<_>, _) = a.svd(false, true).unwrap(); - assert!(u.is_none()); - assert!(vt.is_some()); - let vt = vt.unwrap(); - assert_eq!(vt.dim().0, m); - assert_eq!(vt.dim().1, m); -} - -fn test_diag_only(a: &Array2) { - println!("a = \n{:?}", a); - let (u, _s, vt): (_, Array1<_>, _) = a.svd(false, false).unwrap(); - assert!(u.is_none()); - assert!(vt.is_none()); -} - -macro_rules! test_svd_impl { - ($type:ty, $test:ident, $n:expr, $m:expr) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using(($n, $m), &mut rng); - $test::<$type>(&a); - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using(($n, $m).f(), &mut rng); - $test::<$type>(&a); - } - } - }; -} - -test_svd_impl!(f64, test, 3, 3); -test_svd_impl!(f64, test_no_vt, 3, 3); -test_svd_impl!(f64, test_no_u, 3, 3); -test_svd_impl!(f64, test_diag_only, 3, 3); -test_svd_impl!(f64, test, 4, 3); -test_svd_impl!(f64, test_no_vt, 4, 3); -test_svd_impl!(f64, test_no_u, 4, 3); -test_svd_impl!(f64, test_diag_only, 4, 3); -test_svd_impl!(f64, test, 3, 4); -test_svd_impl!(f64, test_no_vt, 3, 4); -test_svd_impl!(f64, test_no_u, 3, 4); -test_svd_impl!(f64, test_diag_only, 3, 4); -test_svd_impl!(c64, test, 3, 3); -test_svd_impl!(c64, test_no_vt, 3, 3); -test_svd_impl!(c64, test_no_u, 3, 3); -test_svd_impl!(c64, test_diag_only, 3, 3); -test_svd_impl!(c64, test, 4, 3); -test_svd_impl!(c64, test_no_vt, 4, 3); -test_svd_impl!(c64, test_no_u, 4, 3); -test_svd_impl!(c64, test_diag_only, 4, 3); -test_svd_impl!(c64, test, 3, 4); -test_svd_impl!(c64, test_no_vt, 3, 4); -test_svd_impl!(c64, test_no_u, 3, 4); -test_svd_impl!(c64, test_diag_only, 3, 4); diff --git a/ndarray-linalg/tests/svddc.rs b/ndarray-linalg/tests/svddc.rs deleted file mode 100644 index 60c6bd66..00000000 --- a/ndarray-linalg/tests/svddc.rs +++ /dev/null @@ -1,83 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -fn test(a: &Array2, flag: JobSvd) { - let (n, m) = a.dim(); - let k = n.min(m); - let answer = a.clone(); - println!("a = \n{:?}", a); - let (u, s, vt): (_, Array1<_>, _) = a.svddc(flag).unwrap(); - let mut sm: Array2 = match flag { - JobSvd::All => Array::zeros((n, m)), - JobSvd::Some => Array::zeros((k, k)), - JobSvd::None => { - assert!(u.is_none()); - assert!(vt.is_none()); - return; - } - }; - let u: Array2<_> = u.unwrap(); - let vt: Array2<_> = vt.unwrap(); - println!("u = \n{:?}", &u); - println!("s = \n{:?}", &s); - println!("v = \n{:?}", &vt); - for i in 0..k { - sm[(i, i)] = T::from_real(s[i]); - } - assert_close_l2!(&u.dot(&sm).dot(&vt), &answer, T::real(1e-7)); -} - -macro_rules! test_svd_impl { - ($scalar:ty, $n:expr, $m:expr) => { - paste::item! { - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using(($n, $m), &mut rng); - test::<$scalar>(&a, JobSvd::All); - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using(($n, $m), &mut rng); - test::<$scalar>(&a, JobSvd::Some); - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using(($n, $m), &mut rng); - test::<$scalar>(&a, JobSvd::None); - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using(($n, $m).f(), &mut rng); - test::<$scalar>(&a, JobSvd::All); - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using(($n, $m).f(), &mut rng); - test::<$scalar>(&a, JobSvd::Some); - } - - #[test] - fn []() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a = random_using(($n, $m).f(), &mut rng); - test::<$scalar>(&a, JobSvd::None); - } - } - }; -} - -test_svd_impl!(f64, 3, 3); -test_svd_impl!(f64, 4, 3); -test_svd_impl!(f64, 3, 4); -test_svd_impl!(c64, 3, 3); -test_svd_impl!(c64, 4, 3); -test_svd_impl!(c64, 3, 4); diff --git a/ndarray-linalg/tests/trace.rs b/ndarray-linalg/tests/trace.rs deleted file mode 100644 index f93bb52b..00000000 --- a/ndarray-linalg/tests/trace.rs +++ /dev/null @@ -1,9 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[test] -fn trace() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let a: Array2 = random_using((3, 3), &mut rng); - assert_rclose!(a.trace().unwrap(), a[(0, 0)] + a[(1, 1)] + a[(2, 2)], 1e-7); -} diff --git a/ndarray-linalg/tests/triangular.rs b/ndarray-linalg/tests/triangular.rs deleted file mode 100644 index 4ddf0a8b..00000000 --- a/ndarray-linalg/tests/triangular.rs +++ /dev/null @@ -1,132 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -fn test1d(uplo: UPLO, a: &ArrayBase, b: &ArrayBase, tol: A::Real) -where - A: Scalar + Lapack, - Sa: Data, - Sb: DataMut + DataOwned, -{ - println!("a = {:?}", a); - println!("b = {:?}", b); - let x = a.solve_triangular(uplo, Diag::NonUnit, b).unwrap(); - println!("x = {:?}", &x); - let b_ = a.dot(&x); - println!("Ax = {:?}", &b_); - assert_close_l2!(&b_, b, tol); -} - -fn test2d(uplo: UPLO, a: &ArrayBase, b: &ArrayBase, tol: A::Real) -where - A: Scalar + Lapack, - Sa: Data, - Sb: DataMut + DataOwned + Data + RawDataClone, -{ - println!("a = {:?}", a); - println!("b = {:?}", b); - let x = a.solve_triangular(uplo, Diag::NonUnit, b).unwrap(); - println!("x = {:?}", &x); - let b_ = a.dot(&x); - println!("Ax = {:?}", &b_); - assert_close_l2!(&b_, b, tol); -} - -#[test] -fn triangular_1d_upper() { - let n = 3; - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array1 = random_using(n, &mut rng); - let a: Array2 = random_using((n, n), &mut rng).into_triangular(UPLO::Upper); - test1d(UPLO::Upper, &a, &b, 1e-7); -} - -#[test] -fn triangular_1d_lower() { - let n = 3; - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array1 = random_using(n, &mut rng); - let a: Array2 = random_using((n, n), &mut rng).into_triangular(UPLO::Lower); - test1d(UPLO::Lower, &a, &b, 1e-7); -} - -#[test] -fn triangular_1d_upper_t() { - let n = 3; - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array1 = random_using(n, &mut rng); - let a: Array2 = random_using((n, n).f(), &mut rng).into_triangular(UPLO::Upper); - test1d(UPLO::Upper, &a, &b, 1e-7); -} - -#[test] -fn triangular_1d_lower_t() { - let n = 3; - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array1 = random_using(n, &mut rng); - let a: Array2 = random_using((n, n).f(), &mut rng).into_triangular(UPLO::Lower); - test1d(UPLO::Lower, &a, &b, 1e-7); -} - -#[test] -fn triangular_2d_upper() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array2 = random_using((3, 4), &mut rng); - let a: Array2 = random_using((3, 3), &mut rng).into_triangular(UPLO::Upper); - test2d(UPLO::Upper, &a, &b, 1e-7); -} - -#[test] -fn triangular_2d_lower() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array2 = random_using((3, 4), &mut rng); - let a: Array2 = random_using((3, 3), &mut rng).into_triangular(UPLO::Lower); - test2d(UPLO::Lower, &a, &b, 1e-7); -} - -#[test] -fn triangular_2d_lower_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array2 = random_using((3, 4), &mut rng); - let a: Array2 = random_using((3, 3).f(), &mut rng).into_triangular(UPLO::Lower); - test2d(UPLO::Lower, &a, &b, 1e-7); -} - -#[test] -fn triangular_2d_upper_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array2 = random_using((3, 4), &mut rng); - let a: Array2 = random_using((3, 3).f(), &mut rng).into_triangular(UPLO::Upper); - test2d(UPLO::Upper, &a, &b, 1e-7); -} - -#[test] -fn triangular_2d_upper_bt() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array2 = random_using((3, 4).f(), &mut rng); - let a: Array2 = random_using((3, 3), &mut rng).into_triangular(UPLO::Upper); - test2d(UPLO::Upper, &a, &b, 1e-7); -} - -#[test] -fn triangular_2d_lower_bt() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array2 = random_using((3, 4).f(), &mut rng); - let a: Array2 = random_using((3, 3), &mut rng).into_triangular(UPLO::Lower); - test2d(UPLO::Lower, &a, &b, 1e-7); -} - -#[test] -fn triangular_2d_lower_t_bt() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array2 = random_using((3, 4).f(), &mut rng); - let a: Array2 = random_using((3, 3).f(), &mut rng).into_triangular(UPLO::Lower); - test2d(UPLO::Lower, &a, &b, 1e-7); -} - -#[test] -fn triangular_2d_upper_t_bt() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let b: Array2 = random_using((3, 4).f(), &mut rng); - let a: Array2 = random_using((3, 3).f(), &mut rng).into_triangular(UPLO::Upper); - test2d(UPLO::Upper, &a, &b, 1e-7); -} diff --git a/ndarray-linalg/tests/tridiagonal.rs b/ndarray-linalg/tests/tridiagonal.rs deleted file mode 100644 index 513d625b..00000000 --- a/ndarray-linalg/tests/tridiagonal.rs +++ /dev/null @@ -1,267 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[test] -fn extract_tridiagonal() { - let a: Array2 = arr2(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]); - let t = a.extract_tridiagonal().unwrap(); - assert_close_l2!(&arr1(&t.dl), &arr1(&[4.0, 8.0]), 1e-7); - assert_close_l2!(&arr1(&t.d), &arr1(&[1.0, 5.0, 9.0]), 1e-7); - assert_close_l2!(&arr1(&t.du), &arr1(&[2.0, 6.0]), 1e-7); -} - -#[test] -fn tridiagonal_index() { - let a: Array2 = arr2(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]); - let t1 = a.extract_tridiagonal().unwrap(); - let mut t2 = Array2::::eye(3).extract_tridiagonal().unwrap(); - t2[[0, 1]] = 2.0; - t2[[1, 0]] = 4.0; - t2[[1, 1]] += 4.0; - t2[[1, 2]] = 6.0; - t2[[2, 1]] = 8.0; - t2[[2, 2]] += 8.0; - assert_eq!(t1.dl, t2.dl); - assert_eq!(t1.d, t2.d); - assert_eq!(t1.du, t2.du); -} - -#[test] -fn opnorm_tridiagonal() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let mut a: Array2 = random_using((4, 4), &mut rng); - a[[0, 2]] = 0.0; - a[[0, 3]] = 0.0; - a[[1, 3]] = 0.0; - a[[2, 0]] = 0.0; - a[[3, 0]] = 0.0; - a[[3, 1]] = 0.0; - let t = a.extract_tridiagonal().unwrap(); - assert_aclose!(a.opnorm_one().unwrap(), t.opnorm_one().unwrap(), 1e-7); - assert_aclose!(a.opnorm_inf().unwrap(), t.opnorm_inf().unwrap(), 1e-7); - assert_aclose!(a.opnorm_fro().unwrap(), t.opnorm_fro().unwrap(), 1e-7); -} - -#[test] -fn solve_tridiagonal_f64() { - // https://www.nag-j.co.jp/lapack/dgttrs.htm - let a: Array2 = arr2(&[ - [3.0, 2.1, 0.0, 0.0, 0.0], - [3.4, 2.3, -1.0, 0.0, 0.0], - [0.0, 3.6, -5.0, 1.9, 0.0], - [0.0, 0.0, 7.0, -0.9, 8.0], - [0.0, 0.0, 0.0, -6.0, 7.1], - ]); - let b: Array2 = arr2(&[ - [2.7, 6.6], - [-0.5, 10.8], - [2.6, -3.2], - [0.6, -11.2], - [2.7, 19.1], - ]); - let x: Array2 = arr2(&[ - [-4.0, 5.0], - [7.0, -4.0], - [3.0, -3.0], - [-4.0, -2.0], - [-3.0, 1.0], - ]); - let y = a.solve_tridiagonal_into(b).unwrap(); - assert_close_l2!(&x, &y, 1e-7); -} -//`*gttrf`, `*gtcon` and `*gttrs` -#[test] -fn solve_tridiagonal_c64() { - // https://www.nag-j.co.jp/lapack/zgttrs.htm - let a: Array2 = arr2(&[ - [ - c64::new(-1.3, 1.3), - c64::new(2.0, -1.0), - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - ], - [ - c64::new(1.0, -2.0), - c64::new(-1.3, 1.3), - c64::new(2.0, 1.0), - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - ], - [ - c64::new(0.0, 0.0), - c64::new(1.0, 1.0), - c64::new(-1.3, 3.3), - c64::new(-1.0, 1.0), - c64::new(0.0, 0.0), - ], - [ - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - c64::new(2.0, -3.0), - c64::new(-0.3, 4.3), - c64::new(1.0, -1.0), - ], - [ - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - c64::new(1.0, 1.0), - c64::new(-3.3, 1.3), - ], - ]); - let b: Array2 = arr2(&[ - [c64::new(2.4, -5.0), c64::new(2.7, 6.9)], - [c64::new(3.4, 18.2), c64::new(-6.9, -5.3)], - [c64::new(-14.7, 9.7), c64::new(-6.0, -0.6)], - [c64::new(31.9, -7.7), c64::new(-3.9, 9.3)], - [c64::new(-1.0, 1.6), c64::new(-3.0, 12.2)], - ]); - let x: Array2 = arr2(&[ - [c64::new(1.0, 1.0), c64::new(2.0, -1.0)], - [c64::new(3.0, -1.0), c64::new(1.0, 2.0)], - [c64::new(4.0, 5.0), c64::new(-1.0, 1.0)], - [c64::new(-1.0, -2.0), c64::new(2.0, 1.0)], - [c64::new(1.0, -1.0), c64::new(2.0, -2.0)], - ]); - let y = a.solve_tridiagonal_into(b).unwrap(); - assert_close_l2!(&x, &y, 1e-7); -} - -#[test] -fn solve_tridiagonal_random() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let mut a: Array2 = random_using((3, 3), &mut rng); - a[[0, 2]] = 0.0; - a[[2, 0]] = 0.0; - let x: Array1 = random_using(3, &mut rng); - let b1 = a.dot(&x); - let b2 = b1.clone(); - let y1 = a.solve_tridiagonal_into(b1).unwrap(); - let y2 = a.solve_into(b2).unwrap(); - assert_close_l2!(&x, &y1, 1e-7); - assert_close_l2!(&y1, &y2, 1e-7); -} - -#[test] -fn solve_tridiagonal_random_t() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let mut a: Array2 = random_using((3, 3), &mut rng); - a[[0, 2]] = 0.0; - a[[2, 0]] = 0.0; - let x: Array1 = random_using(3, &mut rng); - let at = a.t(); - let b1 = at.dot(&x); - let b2 = b1.clone(); - let y1 = a.solve_t_tridiagonal_into(b1).unwrap(); - let y2 = a.solve_t_into(b2).unwrap(); - assert_close_l2!(&x, &y1, 1e-7); - assert_close_l2!(&y1, &y2, 1e-7); -} - -#[test] -fn extract_tridiagonal_solve_random() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let mut a: Array2 = random_using((3, 3), &mut rng); - a[[0, 2]] = 0.0; - a[[2, 0]] = 0.0; - let tridiag = a.extract_tridiagonal().unwrap(); - let x: Array1 = random_using(3, &mut rng); - let b1 = a.dot(&x); - let b2 = b1.clone(); - let y1 = tridiag.solve_tridiagonal_into(b1).unwrap(); - let y2 = a.solve_into(b2).unwrap(); - assert_close_l2!(&x, &y1, 1e-7); - assert_close_l2!(&y1, &y2, 1e-7); -} - -#[test] -fn det_tridiagonal_f64() { - let a: Array2 = arr2(&[[10.0, -9.0, 0.0], [7.0, -12.0, 11.0], [0.0, 10.0, 3.0]]); - assert_aclose!(a.det_tridiagonal().unwrap(), -1271.0, 1e-7); - assert_aclose!(a.det_tridiagonal().unwrap(), a.det().unwrap(), 1e-7); -} - -#[test] -fn det_tridiagonal_random() { - let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); - let mut a: Array2 = random_using((3, 3), &mut rng); - a[[0, 2]] = 0.0; - a[[2, 0]] = 0.0; - assert_aclose!(a.det_tridiagonal().unwrap(), a.det().unwrap(), 1e-7); -} - -#[test] -fn rcond_tridiagonal_f64() { - // https://www.nag-j.co.jp/lapack/dgtcon.htm - let a: Array2 = arr2(&[ - [3.0, 2.1, 0.0, 0.0, 0.0], - [3.4, 2.3, -1.0, 0.0, 0.0], - [0.0, 3.6, -5.0, 1.9, 0.0], - [0.0, 0.0, 7.0, -0.9, 8.0], - [0.0, 0.0, 0.0, -6.0, 7.1], - ]); - assert_aclose!(1.0 / a.rcond_tridiagonal().unwrap(), 9.27e1, 0.1); - assert_aclose!(a.rcond_tridiagonal().unwrap(), a.rcond().unwrap(), 1e-3); -} - -#[test] -fn rcond_tridiagonal_c64() { - // https://www.nag-j.co.jp/lapack/dgtcon.htm - let a: Array2 = arr2(&[ - [ - c64::new(-1.3, 1.3), - c64::new(2.0, -1.0), - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - ], - [ - c64::new(1.0, -2.0), - c64::new(-1.3, 1.3), - c64::new(2.0, 1.0), - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - ], - [ - c64::new(0.0, 0.0), - c64::new(1.0, 1.0), - c64::new(-1.3, 3.3), - c64::new(-1.0, 1.0), - c64::new(0.0, 0.0), - ], - [ - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - c64::new(2.0, -3.0), - c64::new(-0.3, 4.3), - c64::new(1.0, -1.0), - ], - [ - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - c64::new(0.0, 0.0), - c64::new(1.0, 1.0), - c64::new(-3.3, 1.3), - ], - ]); - assert_aclose!(1.0 / a.rcond_tridiagonal().unwrap(), 1.84e2, 1.0); - assert_aclose!(a.rcond_tridiagonal().unwrap(), a.rcond().unwrap(), 1e-3); -} - -#[test] -fn rcond_tridiagonal_identity() { - macro_rules! rcond_identity { - ($elem:ty, $rows:expr, $atol:expr) => { - let a = Array2::<$elem>::eye($rows); - assert_aclose!(a.rcond_tridiagonal().unwrap(), 1., $atol); - }; - } - for rows in 2..6 { - // cannot make 1x1 tridiagonal matrices. - rcond_identity!(f64, rows, 1e-9); - rcond_identity!(f32, rows, 1e-3); - rcond_identity!(c64, rows, 1e-9); - rcond_identity!(c32, rows, 1e-3); - } -} diff --git a/ndarray-linalg/tests/vector.rs b/ndarray-linalg/tests/vector.rs deleted file mode 100644 index a61bedd6..00000000 --- a/ndarray-linalg/tests/vector.rs +++ /dev/null @@ -1,40 +0,0 @@ -use ndarray::*; -use ndarray_linalg::*; - -#[test] -fn vector_norm() { - let a = Array::range(1., 10., 1.); - assert_rclose!(a.norm(), 285.0.sqrt(), 1e-7); -} - -#[test] -fn vector_norm_l1() { - let a = arr1(&[1.0, -1.0]); - assert_rclose!(a.norm_l1(), 2.0, 1e-7); - let b = arr2(&[[0.0, -1.0], [1.0, 0.0]]); - assert_rclose!(b.norm_l1(), 2.0, 1e-7); -} - -#[test] -fn vector_norm_max() { - let a = arr1(&[1.0, 1.0, -3.0]); - assert_rclose!(a.norm_max(), 3.0, 1e-7); - let b = arr2(&[[1.0, 3.0], [1.0, -4.0]]); - assert_rclose!(b.norm_max(), 4.0, 1e-7); -} - -#[test] -fn vector_norm_l1_rc() { - let a = rcarr1(&[1.0, -1.0]); - assert_rclose!(a.norm_l1(), 2.0, 1e-7); - let b = rcarr2(&[[0.0, -1.0], [1.0, 0.0]]); - assert_rclose!(b.norm_l1(), 2.0, 1e-7); -} - -#[test] -fn vector_norm_max_rc() { - let a = rcarr1(&[1.0, 1.0, -3.0]); - assert_rclose!(a.norm_max(), 3.0, 1e-7); - let b = rcarr2(&[[1.0, 3.0], [1.0, -4.0]]); - assert_rclose!(b.norm_max(), 4.0, 1e-7); -} diff --git a/ndarray_linalg/all.html b/ndarray_linalg/all.html new file mode 100644 index 00000000..7d5517e9 --- /dev/null +++ b/ndarray_linalg/all.html @@ -0,0 +1,25 @@ +List of all items in this crate + + + + + + +

List of all items

Structs

Enums

Traits

Macros

Functions

Typedefs

+ \ No newline at end of file diff --git a/ndarray_linalg/assert/fn.aclose.html b/ndarray_linalg/assert/fn.aclose.html new file mode 100644 index 00000000..24947d59 --- /dev/null +++ b/ndarray_linalg/assert/fn.aclose.html @@ -0,0 +1,27 @@ +aclose in ndarray_linalg::assert - Rust + + + + + + +
pub fn aclose<A: Scalar>(test: A, truth: A, atol: A::Real)
Expand description

check two values are close in terms of the absolute tolerance

+
+ \ No newline at end of file diff --git a/ndarray_linalg/assert/fn.close_l1.html b/ndarray_linalg/assert/fn.close_l1.html new file mode 100644 index 00000000..6912f1ae --- /dev/null +++ b/ndarray_linalg/assert/fn.close_l1.html @@ -0,0 +1,27 @@ +close_l1 in ndarray_linalg::assert - Rust + + + + + + +
pub fn close_l1<A, S1, S2, D>(
    test: &ArrayBase<S1, D>,
    truth: &ArrayBase<S2, D>,
    rtol: A::Real
) where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug
Expand description

check two arrays are close in L1 norm

+
+ \ No newline at end of file diff --git a/ndarray_linalg/assert/fn.close_l2.html b/ndarray_linalg/assert/fn.close_l2.html new file mode 100644 index 00000000..4fd30303 --- /dev/null +++ b/ndarray_linalg/assert/fn.close_l2.html @@ -0,0 +1,27 @@ +close_l2 in ndarray_linalg::assert - Rust + + + + + + +
pub fn close_l2<A, S1, S2, D>(
    test: &ArrayBase<S1, D>,
    truth: &ArrayBase<S2, D>,
    rtol: A::Real
) where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug
Expand description

check two arrays are close in L2 norm

+
+ \ No newline at end of file diff --git a/ndarray_linalg/assert/fn.close_max.html b/ndarray_linalg/assert/fn.close_max.html new file mode 100644 index 00000000..939dfd8b --- /dev/null +++ b/ndarray_linalg/assert/fn.close_max.html @@ -0,0 +1,27 @@ +close_max in ndarray_linalg::assert - Rust + + + + + + +
pub fn close_max<A, S1, S2, D>(
    test: &ArrayBase<S1, D>,
    truth: &ArrayBase<S2, D>,
    atol: A::Real
) where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug
Expand description

check two arrays are close in maximum norm

+
+ \ No newline at end of file diff --git a/ndarray_linalg/assert/fn.rclose.html b/ndarray_linalg/assert/fn.rclose.html new file mode 100644 index 00000000..02c8f096 --- /dev/null +++ b/ndarray_linalg/assert/fn.rclose.html @@ -0,0 +1,27 @@ +rclose in ndarray_linalg::assert - Rust + + + + + + +
pub fn rclose<A: Scalar>(test: A, truth: A, rtol: A::Real)
Expand description

check two values are close in terms of the relative tolerance

+
+ \ No newline at end of file diff --git a/ndarray_linalg/assert/index.html b/ndarray_linalg/assert/index.html new file mode 100644 index 00000000..6b22266c --- /dev/null +++ b/ndarray_linalg/assert/index.html @@ -0,0 +1,33 @@ +ndarray_linalg::assert - Rust + + + + + + +
Expand description

Assertions for array

+

Functions

+

check two values are close in terms of the absolute tolerance

+

check two arrays are close in L1 norm

+

check two arrays are close in L2 norm

+

check two arrays are close in maximum norm

+

check two values are close in terms of the relative tolerance

+
+ \ No newline at end of file diff --git a/ndarray_linalg/assert/sidebar-items.js b/ndarray_linalg/assert/sidebar-items.js new file mode 100644 index 00000000..cb177e51 --- /dev/null +++ b/ndarray_linalg/assert/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":[["aclose","check two values are close in terms of the absolute tolerance"],["close_l1","check two arrays are close in L1 norm"],["close_l2","check two arrays are close in L2 norm"],["close_max","check two arrays are close in maximum norm"],["rclose","check two values are close in terms of the relative tolerance"]]}; \ No newline at end of file diff --git a/ndarray_linalg/cholesky/enum.UPLO.html b/ndarray_linalg/cholesky/enum.UPLO.html new file mode 100644 index 00000000..3467a80e --- /dev/null +++ b/ndarray_linalg/cholesky/enum.UPLO.html @@ -0,0 +1,49 @@ +UPLO in ndarray_linalg::cholesky - Rust + + + + + + +
#[repr(u8)]
+pub enum UPLO {
+    Upper,
+    Lower,
+}
Expand description

Upper/Lower specification for seveal usages

+

Variants

Upper

Lower

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/index.html b/ndarray_linalg/cholesky/index.html new file mode 100644 index 00000000..6482659c --- /dev/null +++ b/ndarray_linalg/cholesky/index.html @@ -0,0 +1,79 @@ +ndarray_linalg::cholesky - Rust + + + + + + +
Expand description

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrices

+

See the Wikipedia page about Cholesky +decomposition for +more information.

+

Example

+

Using the Cholesky decomposition of A for various operations, where A +is a Hermitian (or real symmetric) positive definite matrix:

+ +
#[macro_use]
+extern crate ndarray;
+extern crate ndarray_linalg;
+
+use ndarray::prelude::*;
+use ndarray_linalg::cholesky::*;
+
+let a: Array2<f64> = array![
+    [  4.,  12., -16.],
+    [ 12.,  37., -43.],
+    [-16., -43.,  98.]
+];
+
+// Obtain `L`
+let lower = a.cholesky(UPLO::Lower).unwrap();
+assert!(lower.abs_diff_eq(&array![
+    [ 2., 0., 0.],
+    [ 6., 1., 0.],
+    [-8., 5., 3.]
+], 1e-9));
+
+// Find the determinant of `A`
+let det = a.detc().unwrap();
+assert!((det - 36.).abs() < 1e-9);
+
+// Solve `A * x = b`
+let b = array![4., 13., -11.];
+let x = a.solvec(&b).unwrap();
+assert!(x.abs_diff_eq(&array![-2., 1., 0.], 1e-9));
+

Structs

+

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix

+

Enums

+

Upper/Lower specification for seveal usages

+

Traits

+

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference

+

Cholesky decomposition of Hermitian (or real symmetric) positive definite mutable reference of matrix

+

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix

+

Determinant of Hermitian (or real symmetric) positive definite matrix ref

+

Determinant of Hermitian (or real symmetric) positive definite matrix

+

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference

+

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix

+

Inverse of Hermitian (or real symmetric) positive definite matrix ref

+

Inverse of Hermitian (or real symmetric) positive definite matrix

+

Solve systems of linear equations with Hermitian (or real symmetric) +positive definite coefficient matrices

+
+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/sidebar-items.js b/ndarray_linalg/cholesky/sidebar-items.js new file mode 100644 index 00000000..b9ff7745 --- /dev/null +++ b/ndarray_linalg/cholesky/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["UPLO","Upper/Lower specification for seveal usages"]],"struct":[["CholeskyFactorized","Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix"]],"trait":[["Cholesky","Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference"],["CholeskyInplace","Cholesky decomposition of Hermitian (or real symmetric) positive definite mutable reference of matrix"],["CholeskyInto","Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix"],["DeterminantC","Determinant of Hermitian (or real symmetric) positive definite matrix ref"],["DeterminantCInto","Determinant of Hermitian (or real symmetric) positive definite matrix"],["FactorizeC","Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference"],["FactorizeCInto","Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix"],["InverseC","Inverse of Hermitian (or real symmetric) positive definite matrix ref"],["InverseCInto","Inverse of Hermitian (or real symmetric) positive definite matrix"],["SolveC","Solve systems of linear equations with Hermitian (or real symmetric) positive definite coefficient matrices"]]}; \ No newline at end of file diff --git a/ndarray_linalg/cholesky/struct.CholeskyFactorized.html b/ndarray_linalg/cholesky/struct.CholeskyFactorized.html new file mode 100644 index 00000000..fe3a2335 --- /dev/null +++ b/ndarray_linalg/cholesky/struct.CholeskyFactorized.html @@ -0,0 +1,75 @@ +CholeskyFactorized in ndarray_linalg::cholesky - Rust + + + + + + +
pub struct CholeskyFactorized<S: Data> {
+    pub factor: ArrayBase<S, Ix2>,
+    pub uplo: UPLO,
+}
Expand description

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix

+

Fields

factor: ArrayBase<S, Ix2>

L from the decomposition A = L * L^H or U from the decomposition +A = U^H * U.

+
uplo: UPLO

If this is UPLO::Lower, then self.factor is L. If this is +UPLO::Upper, then self.factor is U.

+

Implementations

Returns L from the Cholesky decomposition A = L * L^H.

+

If self.uplo == UPLO::Lower, then no computations need to be +performed; otherwise, the conjugate transpose of self.factor is +calculated.

+

Returns U from the Cholesky decomposition A = U^H * U.

+

If self.uplo == UPLO::Upper, then no computations need to be +performed; otherwise, the conjugate transpose of self.factor is +calculated.

+

Trait Implementations

Computes the determinant of the Hermitian (or real symmetric) positive +definite matrix. Read more

+

Computes the natural log of the determinant of the Hermitian (or real +symmetric) positive definite matrix. Read more

+

Computes the determinant of the Hermitian (or real symmetric) positive +definite matrix. Read more

+

Computes the natural log of the determinant of the Hermitian (or real +symmetric) positive definite matrix. Read more

+

Computes the inverse of the Hermitian (or real symmetric) positive +definite matrix. Read more

+

Computes the inverse of the Hermitian (or real symmetric) positive +definite matrix. Read more

+

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) positive definite matrix A, where A is self, b is +the argument, and x is the successful result. The value of x is +also assigned to the argument. Read more

+

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) positive definite matrix A, where A is self, b is +the argument, and x is the successful result. Read more

+

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) positive definite matrix A, where A is self, b is +the argument, and x is the successful result. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.Cholesky.html b/ndarray_linalg/cholesky/trait.Cholesky.html new file mode 100644 index 00000000..3bad6445 --- /dev/null +++ b/ndarray_linalg/cholesky/trait.Cholesky.html @@ -0,0 +1,37 @@ +Cholesky in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait Cholesky {
+    type Output;
+
+    fn cholesky(&self, uplo: UPLO) -> Result<Self::Output>;
+}
Expand description

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference

+

Required Associated Types

Required Methods

Computes the Cholesky decomposition of the Hermitian (or real +symmetric) positive definite matrix.

+

If the argument is UPLO::Upper, then computes the decomposition A = U^H * U using the upper triangular portion of A and returns U. +Otherwise, if the argument is UPLO::Lower, computes the decomposition +A = L * L^H using the lower triangular portion of A and returns +L.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.CholeskyInplace.html b/ndarray_linalg/cholesky/trait.CholeskyInplace.html new file mode 100644 index 00000000..79c31885 --- /dev/null +++ b/ndarray_linalg/cholesky/trait.CholeskyInplace.html @@ -0,0 +1,35 @@ +CholeskyInplace in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait CholeskyInplace {
+    fn cholesky_inplace(&mut self, uplo: UPLO) -> Result<&mut Self>;
+}
Expand description

Cholesky decomposition of Hermitian (or real symmetric) positive definite mutable reference of matrix

+

Required Methods

Computes the Cholesky decomposition of the Hermitian (or real +symmetric) positive definite matrix, writing the result (L or U +according to the argument) to self and returning it.

+

If the argument is UPLO::Upper, then computes the decomposition A = U^H * U using the upper triangular portion of A and writes U. +Otherwise, if the argument is UPLO::Lower, computes the decomposition +A = L * L^H using the lower triangular portion of A and writes L.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.CholeskyInto.html b/ndarray_linalg/cholesky/trait.CholeskyInto.html new file mode 100644 index 00000000..44817ce2 --- /dev/null +++ b/ndarray_linalg/cholesky/trait.CholeskyInto.html @@ -0,0 +1,37 @@ +CholeskyInto in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait CholeskyInto {
+    type Output;
+
+    fn cholesky_into(self, uplo: UPLO) -> Result<Self::Output>;
+}
Expand description

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix

+

Required Associated Types

Required Methods

Computes the Cholesky decomposition of the Hermitian (or real +symmetric) positive definite matrix.

+

If the argument is UPLO::Upper, then computes the decomposition A = U^H * U using the upper triangular portion of A and returns U. +Otherwise, if the argument is UPLO::Lower, computes the decomposition +A = L * L^H using the lower triangular portion of A and returns +L.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.DeterminantC.html b/ndarray_linalg/cholesky/trait.DeterminantC.html new file mode 100644 index 00000000..162c095a --- /dev/null +++ b/ndarray_linalg/cholesky/trait.DeterminantC.html @@ -0,0 +1,39 @@ +DeterminantC in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait DeterminantC {
+    type Output;
+
+    fn detc(&self) -> Self::Output;
+    fn ln_detc(&self) -> Self::Output;
+}
Expand description

Determinant of Hermitian (or real symmetric) positive definite matrix ref

+

Required Associated Types

Required Methods

Computes the determinant of the Hermitian (or real symmetric) positive +definite matrix.

+

Computes the natural log of the determinant of the Hermitian (or real +symmetric) positive definite matrix.

+

This method is more robust than .detc() to very small or very large +determinants since it returns the natural logarithm of the determinant +rather than the determinant itself.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.DeterminantCInto.html b/ndarray_linalg/cholesky/trait.DeterminantCInto.html new file mode 100644 index 00000000..69e177ef --- /dev/null +++ b/ndarray_linalg/cholesky/trait.DeterminantCInto.html @@ -0,0 +1,39 @@ +DeterminantCInto in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait DeterminantCInto {
+    type Output;
+
+    fn detc_into(self) -> Self::Output;
+    fn ln_detc_into(self) -> Self::Output;
+}
Expand description

Determinant of Hermitian (or real symmetric) positive definite matrix

+

Required Associated Types

Required Methods

Computes the determinant of the Hermitian (or real symmetric) positive +definite matrix.

+

Computes the natural log of the determinant of the Hermitian (or real +symmetric) positive definite matrix.

+

This method is more robust than .detc_into() to very small or very +large determinants since it returns the natural logarithm of the +determinant rather than the determinant itself.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.FactorizeC.html b/ndarray_linalg/cholesky/trait.FactorizeC.html new file mode 100644 index 00000000..de2b2d5b --- /dev/null +++ b/ndarray_linalg/cholesky/trait.FactorizeC.html @@ -0,0 +1,35 @@ +FactorizeC in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait FactorizeC<S: Data> {
+    fn factorizec(&self, uplo: UPLO) -> Result<CholeskyFactorized<S>>;
+}
Expand description

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference

+

Required Methods

Computes the Cholesky decomposition of the Hermitian (or real +symmetric) positive definite matrix.

+

If the argument is UPLO::Upper, then computes the decomposition A = U^H * U using the upper triangular portion of A and returns the +factorization containing U. Otherwise, if the argument is +UPLO::Lower, computes the decomposition A = L * L^H using the lower +triangular portion of A and returns the factorization containing L.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.FactorizeCInto.html b/ndarray_linalg/cholesky/trait.FactorizeCInto.html new file mode 100644 index 00000000..7dbdab61 --- /dev/null +++ b/ndarray_linalg/cholesky/trait.FactorizeCInto.html @@ -0,0 +1,35 @@ +FactorizeCInto in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait FactorizeCInto<S: Data> {
+    fn factorizec_into(self, uplo: UPLO) -> Result<CholeskyFactorized<S>>;
+}
Expand description

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix

+

Required Methods

Computes the Cholesky decomposition of the Hermitian (or real +symmetric) positive definite matrix.

+

If the argument is UPLO::Upper, then computes the decomposition A = U^H * U using the upper triangular portion of A and returns the +factorization containing U. Otherwise, if the argument is +UPLO::Lower, computes the decomposition A = L * L^H using the lower +triangular portion of A and returns the factorization containing L.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.InverseC.html b/ndarray_linalg/cholesky/trait.InverseC.html new file mode 100644 index 00000000..61fbb586 --- /dev/null +++ b/ndarray_linalg/cholesky/trait.InverseC.html @@ -0,0 +1,33 @@ +InverseC in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait InverseC {
+    type Output;
+
+    fn invc(&self) -> Result<Self::Output>;
+}
Expand description

Inverse of Hermitian (or real symmetric) positive definite matrix ref

+

Required Associated Types

Required Methods

Computes the inverse of the Hermitian (or real symmetric) positive +definite matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.InverseCInto.html b/ndarray_linalg/cholesky/trait.InverseCInto.html new file mode 100644 index 00000000..8c602bb6 --- /dev/null +++ b/ndarray_linalg/cholesky/trait.InverseCInto.html @@ -0,0 +1,33 @@ +InverseCInto in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait InverseCInto {
+    type Output;
+
+    fn invc_into(self) -> Result<Self::Output>;
+}
Expand description

Inverse of Hermitian (or real symmetric) positive definite matrix

+

Required Associated Types

Required Methods

Computes the inverse of the Hermitian (or real symmetric) positive +definite matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/cholesky/trait.SolveC.html b/ndarray_linalg/cholesky/trait.SolveC.html new file mode 100644 index 00000000..5938bdcc --- /dev/null +++ b/ndarray_linalg/cholesky/trait.SolveC.html @@ -0,0 +1,43 @@ +SolveC in ndarray_linalg::cholesky - Rust + + + + + + +
pub trait SolveC<A: Scalar> {
+    fn solvec_inplace<'a, S: DataMut<Elem = A>>(
        &self,
        b: &'a mut ArrayBase<S, Ix1>
    ) -> Result<&'a mut ArrayBase<S, Ix1>>; + + fn solvec<S: Data<Elem = A>>(
        &self,
        b: &ArrayBase<S, Ix1>
    ) -> Result<Array1<A>> { ... } + fn solvec_into<S: DataMut<Elem = A>>(
        &self,
        b: ArrayBase<S, Ix1>
    ) -> Result<ArrayBase<S, Ix1>> { ... } +}
Expand description

Solve systems of linear equations with Hermitian (or real symmetric) +positive definite coefficient matrices

+

Required Methods

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) positive definite matrix A, where A is self, b is +the argument, and x is the successful result. The value of x is +also assigned to the argument.

+

Provided Methods

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) positive definite matrix A, where A is self, b is +the argument, and x is the successful result.

+

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) positive definite matrix A, where A is self, b is +the argument, and x is the successful result.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/convert/fn.flatten.html b/ndarray_linalg/convert/fn.flatten.html new file mode 100644 index 00000000..41c39665 --- /dev/null +++ b/ndarray_linalg/convert/fn.flatten.html @@ -0,0 +1,26 @@ +flatten in ndarray_linalg::convert - Rust + + + + + + +
pub fn flatten<S>(a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix1> where
    S: Data
+ \ No newline at end of file diff --git a/ndarray_linalg/convert/fn.generalize.html b/ndarray_linalg/convert/fn.generalize.html new file mode 100644 index 00000000..3d148c7d --- /dev/null +++ b/ndarray_linalg/convert/fn.generalize.html @@ -0,0 +1,26 @@ +generalize in ndarray_linalg::convert - Rust + + + + + + +
pub fn generalize<A, S, D>(a: Array<A, D>) -> ArrayBase<S, D> where
    S: DataOwned<Elem = A>,
    D: Dimension
+ \ No newline at end of file diff --git a/ndarray_linalg/convert/fn.into_col.html b/ndarray_linalg/convert/fn.into_col.html new file mode 100644 index 00000000..3ba085f2 --- /dev/null +++ b/ndarray_linalg/convert/fn.into_col.html @@ -0,0 +1,26 @@ +into_col in ndarray_linalg::convert - Rust + + + + + + +
pub fn into_col<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2> where
    S: Data
+ \ No newline at end of file diff --git a/ndarray_linalg/convert/fn.into_matrix.html b/ndarray_linalg/convert/fn.into_matrix.html new file mode 100644 index 00000000..2ce4d7ee --- /dev/null +++ b/ndarray_linalg/convert/fn.into_matrix.html @@ -0,0 +1,26 @@ +into_matrix in ndarray_linalg::convert - Rust + + + + + + +
pub fn into_matrix<A, S>(
    l: MatrixLayout,
    a: Vec<A>
) -> Result<ArrayBase<S, Ix2>> where
    S: DataOwned<Elem = A>, 
+ \ No newline at end of file diff --git a/ndarray_linalg/convert/fn.into_row.html b/ndarray_linalg/convert/fn.into_row.html new file mode 100644 index 00000000..324838b6 --- /dev/null +++ b/ndarray_linalg/convert/fn.into_row.html @@ -0,0 +1,26 @@ +into_row in ndarray_linalg::convert - Rust + + + + + + +
pub fn into_row<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2> where
    S: Data
+ \ No newline at end of file diff --git a/ndarray_linalg/convert/fn.replicate.html b/ndarray_linalg/convert/fn.replicate.html new file mode 100644 index 00000000..e7f7f9dd --- /dev/null +++ b/ndarray_linalg/convert/fn.replicate.html @@ -0,0 +1,26 @@ +replicate in ndarray_linalg::convert - Rust + + + + + + +
pub fn replicate<A, Sv, So, D>(a: &ArrayBase<Sv, D>) -> ArrayBase<So, D> where
    A: Copy,
    Sv: Data<Elem = A>,
    So: DataOwned<Elem = A> + DataMut,
    D: Dimension
+ \ No newline at end of file diff --git a/ndarray_linalg/convert/fn.transpose_data.html b/ndarray_linalg/convert/fn.transpose_data.html new file mode 100644 index 00000000..e454179f --- /dev/null +++ b/ndarray_linalg/convert/fn.transpose_data.html @@ -0,0 +1,26 @@ +transpose_data in ndarray_linalg::convert - Rust + + + + + + +
pub fn transpose_data<A, S>(
    a: &mut ArrayBase<S, Ix2>
) -> Result<&mut ArrayBase<S, Ix2>> where
    A: Copy,
    S: DataOwned<Elem = A> + DataMut
+ \ No newline at end of file diff --git a/ndarray_linalg/convert/index.html b/ndarray_linalg/convert/index.html new file mode 100644 index 00000000..932b7e8b --- /dev/null +++ b/ndarray_linalg/convert/index.html @@ -0,0 +1,28 @@ +ndarray_linalg::convert - Rust + + + + + + +
+ \ No newline at end of file diff --git a/ndarray_linalg/convert/sidebar-items.js b/ndarray_linalg/convert/sidebar-items.js new file mode 100644 index 00000000..630692d3 --- /dev/null +++ b/ndarray_linalg/convert/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":[["flatten",""],["generalize",""],["into_col",""],["into_matrix",""],["into_row",""],["replicate",""],["transpose_data",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/diagonal/index.html b/ndarray_linalg/diagonal/index.html new file mode 100644 index 00000000..7273bf31 --- /dev/null +++ b/ndarray_linalg/diagonal/index.html @@ -0,0 +1,30 @@ +ndarray_linalg::diagonal - Rust + + + + + + +
Expand description

Vector as a Diagonal matrix

+

Structs

+

Vector as a Diagonal matrix

+

Traits

+
+ \ No newline at end of file diff --git a/ndarray_linalg/diagonal/sidebar-items.js b/ndarray_linalg/diagonal/sidebar-items.js new file mode 100644 index 00000000..43bae083 --- /dev/null +++ b/ndarray_linalg/diagonal/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":[["Diagonal","Vector as a Diagonal matrix"]],"trait":[["AsDiagonal",""],["IntoDiagonal",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/diagonal/struct.Diagonal.html b/ndarray_linalg/diagonal/struct.Diagonal.html new file mode 100644 index 00000000..e3de84a7 --- /dev/null +++ b/ndarray_linalg/diagonal/struct.Diagonal.html @@ -0,0 +1,44 @@ +Diagonal in ndarray_linalg::diagonal - Rust + + + + + + +
pub struct Diagonal<S: Data> { /* private fields */ }
Expand description

Vector as a Diagonal matrix

+

Trait Implementations

Apply operator in-place

+

Apply operator out-place

+

Apply operator with move

+

Apply operator to matrix out-place

+

Apply operator to matrix in-place

+

Apply operator to matrix with move

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/diagonal/trait.AsDiagonal.html b/ndarray_linalg/diagonal/trait.AsDiagonal.html new file mode 100644 index 00000000..efa446a1 --- /dev/null +++ b/ndarray_linalg/diagonal/trait.AsDiagonal.html @@ -0,0 +1,28 @@ +AsDiagonal in ndarray_linalg::diagonal - Rust + + + + + + +
pub trait AsDiagonal<A> {
+    fn as_diagonal(&self) -> Diagonal<ViewRepr<&A>>;
+}

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/diagonal/trait.IntoDiagonal.html b/ndarray_linalg/diagonal/trait.IntoDiagonal.html new file mode 100644 index 00000000..7655df61 --- /dev/null +++ b/ndarray_linalg/diagonal/trait.IntoDiagonal.html @@ -0,0 +1,28 @@ +IntoDiagonal in ndarray_linalg::diagonal - Rust + + + + + + +
pub trait IntoDiagonal<S: Data> {
+    fn into_diagonal(self) -> Diagonal<S>;
+}

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eig/index.html b/ndarray_linalg/eig/index.html new file mode 100644 index 00000000..8db9d3dc --- /dev/null +++ b/ndarray_linalg/eig/index.html @@ -0,0 +1,30 @@ +ndarray_linalg::eig - Rust + + + + + + +
Expand description

Eigenvalue decomposition for non-symmetric square matrices

+

Traits

+

Eigenvalue decomposition of general matrix reference

+

Calculate eigenvalues without eigenvectors

+
+ \ No newline at end of file diff --git a/ndarray_linalg/eig/sidebar-items.js b/ndarray_linalg/eig/sidebar-items.js new file mode 100644 index 00000000..20be8723 --- /dev/null +++ b/ndarray_linalg/eig/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["Eig","Eigenvalue decomposition of general matrix reference"],["EigVals","Calculate eigenvalues without eigenvectors"]]}; \ No newline at end of file diff --git a/ndarray_linalg/eig/trait.Eig.html b/ndarray_linalg/eig/trait.Eig.html new file mode 100644 index 00000000..a421956a --- /dev/null +++ b/ndarray_linalg/eig/trait.Eig.html @@ -0,0 +1,54 @@ +Eig in ndarray_linalg::eig - Rust + + + + + + +
pub trait Eig {
+    type EigVal;
+    type EigVec;
+
+    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>;
+}
Expand description

Eigenvalue decomposition of general matrix reference

+

Required Associated Types

EigVec is the right eivenvector

+

Required Methods

Calculate eigenvalues with the right eigenvector

+

$$ A u_i = \lambda_i u_i $$

+ +
use ndarray::*;
+use ndarray_linalg::*;
+
+let a: Array2<f64> = array![
+    [-1.01,  0.86, -4.60,  3.31, -4.81],
+    [ 3.98,  0.53, -7.04,  5.29,  3.55],
+    [ 3.30,  8.26, -3.89,  8.20, -1.51],
+    [ 4.43,  4.96, -7.66, -7.33,  6.18],
+    [ 7.31, -6.43, -6.16,  2.47,  5.58],
+];
+let (eigs, vecs) = a.eig().unwrap();
+
+let a = a.map(|v| v.as_c());
+for (&e, vec) in eigs.iter().zip(vecs.axis_iter(Axis(1))) {
+    let ev = vec.map(|v| v * e);
+    let av = a.dot(&vec);
+    assert_close_l2!(&av, &ev, 1e-5);
+}
+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eig/trait.EigVals.html b/ndarray_linalg/eig/trait.EigVals.html new file mode 100644 index 00000000..2ae54048 --- /dev/null +++ b/ndarray_linalg/eig/trait.EigVals.html @@ -0,0 +1,31 @@ +EigVals in ndarray_linalg::eig - Rust + + + + + + +
pub trait EigVals {
+    type EigVal;
+
+    fn eigvals(&self) -> Result<Self::EigVal>;
+}
Expand description

Calculate eigenvalues without eigenvectors

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/index.html b/ndarray_linalg/eigh/index.html new file mode 100644 index 00000000..7bc9bfeb --- /dev/null +++ b/ndarray_linalg/eigh/index.html @@ -0,0 +1,62 @@ +ndarray_linalg::eigh - Rust + + + + + + +
Expand description

Eigendecomposition for Hermitian matrices.

+

For a Hermitian matrix A, this solves the eigenvalue problem A V = V D +for D and V, where D is the diagonal matrix of eigenvalues in +ascending order and V is the orthonormal matrix of corresponding +eigenvectors.

+

For a pair of Hermitian matrices A and B where B is also positive +definite, this solves the generalized eigenvalue problem A V = B V D, +where D is the diagonal matrix of generalized eigenvalues in ascending +order and V is the matrix of corresponding generalized eigenvectors. The +matrix V is normalized such that V^H B V = I.

+

Example

+

Find the eigendecomposition of a Hermitian (or real symmetric) matrix.

+ +
use approx::assert_abs_diff_eq;
+use ndarray::{array, Array2};
+use ndarray_linalg::{Eigh, UPLO};
+
+let a: Array2<f64> = array![
+    [2., 1.],
+    [1., 2.],
+];
+let (eigvals, eigvecs) = a.eigh(UPLO::Lower)?;
+assert_abs_diff_eq!(eigvals, array![1., 3.]);
+assert_abs_diff_eq!(
+    a.dot(&eigvecs),
+    eigvecs.dot(&Array2::from_diag(&eigvals)),
+);
+

Traits

+

Calculate eigenvalues without eigenvectors

+

Calculate eigenvalues without eigenvectors

+

Calculate eigenvalues without eigenvectors

+

Eigenvalue decomposition of Hermite matrix reference

+

Eigenvalue decomposition of mutable reference of Hermite matrix

+

Eigenvalue decomposition of Hermite matrix

+

Calculate symmetric square-root matrix using eigh

+

Calculate symmetric square-root matrix using eigh

+
+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/sidebar-items.js b/ndarray_linalg/eigh/sidebar-items.js new file mode 100644 index 00000000..595ca7d2 --- /dev/null +++ b/ndarray_linalg/eigh/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["EigValsh","Calculate eigenvalues without eigenvectors"],["EigValshInplace","Calculate eigenvalues without eigenvectors"],["EigValshInto","Calculate eigenvalues without eigenvectors"],["Eigh","Eigenvalue decomposition of Hermite matrix reference"],["EighInplace","Eigenvalue decomposition of mutable reference of Hermite matrix"],["EighInto","Eigenvalue decomposition of Hermite matrix"],["SymmetricSqrt","Calculate symmetric square-root matrix using `eigh`"],["SymmetricSqrtInto","Calculate symmetric square-root matrix using `eigh`"]]}; \ No newline at end of file diff --git a/ndarray_linalg/eigh/trait.EigValsh.html b/ndarray_linalg/eigh/trait.EigValsh.html new file mode 100644 index 00000000..d96df343 --- /dev/null +++ b/ndarray_linalg/eigh/trait.EigValsh.html @@ -0,0 +1,31 @@ +EigValsh in ndarray_linalg::eigh - Rust + + + + + + +
pub trait EigValsh {
+    type EigVal;
+
+    fn eigvalsh(&self, uplo: UPLO) -> Result<Self::EigVal>;
+}
Expand description

Calculate eigenvalues without eigenvectors

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/trait.EigValshInplace.html b/ndarray_linalg/eigh/trait.EigValshInplace.html new file mode 100644 index 00000000..6db49e6e --- /dev/null +++ b/ndarray_linalg/eigh/trait.EigValshInplace.html @@ -0,0 +1,31 @@ +EigValshInplace in ndarray_linalg::eigh - Rust + + + + + + +
pub trait EigValshInplace {
+    type EigVal;
+
+    fn eigvalsh_inplace(&mut self, uplo: UPLO) -> Result<Self::EigVal>;
+}
Expand description

Calculate eigenvalues without eigenvectors

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/trait.EigValshInto.html b/ndarray_linalg/eigh/trait.EigValshInto.html new file mode 100644 index 00000000..2afdad4a --- /dev/null +++ b/ndarray_linalg/eigh/trait.EigValshInto.html @@ -0,0 +1,31 @@ +EigValshInto in ndarray_linalg::eigh - Rust + + + + + + +
pub trait EigValshInto {
+    type EigVal;
+
+    fn eigvalsh_into(self, uplo: UPLO) -> Result<Self::EigVal>;
+}
Expand description

Calculate eigenvalues without eigenvectors

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/trait.Eigh.html b/ndarray_linalg/eigh/trait.Eigh.html new file mode 100644 index 00000000..3488bfab --- /dev/null +++ b/ndarray_linalg/eigh/trait.Eigh.html @@ -0,0 +1,32 @@ +Eigh in ndarray_linalg::eigh - Rust + + + + + + +
pub trait Eigh {
+    type EigVal;
+    type EigVec;
+
+    fn eigh(&self, uplo: UPLO) -> Result<(Self::EigVal, Self::EigVec)>;
+}
Expand description

Eigenvalue decomposition of Hermite matrix reference

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/trait.EighInplace.html b/ndarray_linalg/eigh/trait.EighInplace.html new file mode 100644 index 00000000..ebe10e30 --- /dev/null +++ b/ndarray_linalg/eigh/trait.EighInplace.html @@ -0,0 +1,34 @@ +EighInplace in ndarray_linalg::eigh - Rust + + + + + + +
pub trait EighInplace {
+    type EigVal;
+
+    fn eigh_inplace(&mut self, uplo: UPLO) -> Result<(Self::EigVal, &mut Self)>;
+}
Expand description

Eigenvalue decomposition of mutable reference of Hermite matrix

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Solves the generalized eigenvalue problem.

+
Panics
+

Panics if the shapes of the matrices are different.

+

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/trait.EighInto.html b/ndarray_linalg/eigh/trait.EighInto.html new file mode 100644 index 00000000..8d55381c --- /dev/null +++ b/ndarray_linalg/eigh/trait.EighInto.html @@ -0,0 +1,31 @@ +EighInto in ndarray_linalg::eigh - Rust + + + + + + +
pub trait EighInto: Sized {
+    type EigVal;
+
+    fn eigh_into(self, uplo: UPLO) -> Result<(Self::EigVal, Self)>;
+}
Expand description

Eigenvalue decomposition of Hermite matrix

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/trait.SymmetricSqrt.html b/ndarray_linalg/eigh/trait.SymmetricSqrt.html new file mode 100644 index 00000000..05be4e48 --- /dev/null +++ b/ndarray_linalg/eigh/trait.SymmetricSqrt.html @@ -0,0 +1,31 @@ +SymmetricSqrt in ndarray_linalg::eigh - Rust + + + + + + +
pub trait SymmetricSqrt {
+    type Output;
+
+    fn ssqrt(&self, uplo: UPLO) -> Result<Self::Output>;
+}
Expand description

Calculate symmetric square-root matrix using eigh

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/eigh/trait.SymmetricSqrtInto.html b/ndarray_linalg/eigh/trait.SymmetricSqrtInto.html new file mode 100644 index 00000000..ce5abff9 --- /dev/null +++ b/ndarray_linalg/eigh/trait.SymmetricSqrtInto.html @@ -0,0 +1,31 @@ +SymmetricSqrtInto in ndarray_linalg::eigh - Rust + + + + + + +
pub trait SymmetricSqrtInto {
+    type Output;
+
+    fn ssqrt_into(self, uplo: UPLO) -> Result<Self::Output>;
+}
Expand description

Calculate symmetric square-root matrix using eigh

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/enum.TruncatedOrder.html b/ndarray_linalg/enum.TruncatedOrder.html new file mode 100644 index 00000000..ee42de79 --- /dev/null +++ b/ndarray_linalg/enum.TruncatedOrder.html @@ -0,0 +1,47 @@ +TruncatedOrder in ndarray_linalg - Rust + + + + + + +
pub enum TruncatedOrder {
+    Largest,
+    Smallest,
+}
Expand description

Find largest or smallest eigenvalues

+

Variants

Largest

Smallest

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/error/enum.LinalgError.html b/ndarray_linalg/error/enum.LinalgError.html new file mode 100644 index 00000000..71276978 --- /dev/null +++ b/ndarray_linalg/error/enum.LinalgError.html @@ -0,0 +1,70 @@ +LinalgError in ndarray_linalg::error - Rust + + + + + + +
pub enum LinalgError {
+    NotSquare {
+        rows: i32,
+        cols: i32,
+    },
+    Lapack(Error),
+    InvalidStride {
+        s0: Ixs,
+        s1: Ixs,
+    },
+    MemoryNotCont,
+    NotStandardShape {
+        obj: &'static str,
+        rows: i32,
+        cols: i32,
+    },
+    Shape(ShapeError),
+}
Expand description

Master Error type of this crate

+

Variants

NotSquare

Fields

rows: i32
cols: i32

Matrix is not square

+

Lapack(Error)

LAPACK subroutine returns non-zero code

+

InvalidStride

Fields

s0: Ixs
s1: Ixs

Strides of the array is not supported

+

MemoryNotCont

Memory is not aligned continously

+

NotStandardShape

Fields

obj: &'static str
rows: i32
cols: i32

Obj cannot be made from a (rows, cols) matrix

+

Shape(ShapeError)

Strides of the array is not supported

+

Trait Implementations

Formats the value using the given formatter. Read more

+

Formats the value using the given formatter. Read more

+

The lower-level source of this error, if any. Read more

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. Read more

+
👎 Deprecated since 1.42.0:

use the Display impl or to_string()

+
👎 Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

+

Converts to this type from the input type.

+

Converts to this type from the input type.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

Converts the given value to a String. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/error/index.html b/ndarray_linalg/error/index.html new file mode 100644 index 00000000..b548c9f3 --- /dev/null +++ b/ndarray_linalg/error/index.html @@ -0,0 +1,30 @@ +ndarray_linalg::error - Rust + + + + + + +
Expand description

Define Errors

+

Enums

+

Master Error type of this crate

+

Type Definitions

+
+ \ No newline at end of file diff --git a/ndarray_linalg/error/sidebar-items.js b/ndarray_linalg/error/sidebar-items.js new file mode 100644 index 00000000..162e18de --- /dev/null +++ b/ndarray_linalg/error/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["LinalgError","Master Error type of this crate"]],"type":[["Result",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/error/type.Result.html b/ndarray_linalg/error/type.Result.html new file mode 100644 index 00000000..08d0e0cb --- /dev/null +++ b/ndarray_linalg/error/type.Result.html @@ -0,0 +1,26 @@ +Result in ndarray_linalg::error - Rust + + + + + + +
+

Type Definition ndarray_linalg::error::Result

source · []
pub type Result<T> = Result<T, LinalgError>;
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.conjugate.html b/ndarray_linalg/generate/fn.conjugate.html new file mode 100644 index 00000000..1222c295 --- /dev/null +++ b/ndarray_linalg/generate/fn.conjugate.html @@ -0,0 +1,27 @@ +conjugate in ndarray_linalg::generate - Rust + + + + + + +
pub fn conjugate<A, Si, So>(a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2> where
    A: Scalar,
    Si: Data<Elem = A>,
    So: DataOwned<Elem = A> + DataMut
Expand description

Hermite conjugate matrix

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.from_diag.html b/ndarray_linalg/generate/fn.from_diag.html new file mode 100644 index 00000000..353a0139 --- /dev/null +++ b/ndarray_linalg/generate/fn.from_diag.html @@ -0,0 +1,27 @@ +from_diag in ndarray_linalg::generate - Rust + + + + + + +
pub fn from_diag<A>(d: &[A]) -> Array2<A> where
    A: Scalar
Expand description

construct matrix from diag

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.hstack.html b/ndarray_linalg/generate/fn.hstack.html new file mode 100644 index 00000000..2f5a5eb8 --- /dev/null +++ b/ndarray_linalg/generate/fn.hstack.html @@ -0,0 +1,27 @@ +hstack in ndarray_linalg::generate - Rust + + + + + + +
pub fn hstack<A, S>(xs: &[ArrayBase<S, Ix1>]) -> Result<Array<A, Ix2>> where
    A: Scalar,
    S: Data<Elem = A>, 
Expand description

stack vectors into matrix horizontally

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.random.html b/ndarray_linalg/generate/fn.random.html new file mode 100644 index 00000000..11547af2 --- /dev/null +++ b/ndarray_linalg/generate/fn.random.html @@ -0,0 +1,27 @@ +random in ndarray_linalg::generate - Rust + + + + + + +
pub fn random<A, S, Sh, D>(sh: Sh) -> ArrayBase<S, D> where
    A: Scalar,
    S: DataOwned<Elem = A>,
    D: Dimension,
    Sh: ShapeBuilder<Dim = D>, 
Expand description

Generate random array

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.random_hermite.html b/ndarray_linalg/generate/fn.random_hermite.html new file mode 100644 index 00000000..d13ace20 --- /dev/null +++ b/ndarray_linalg/generate/fn.random_hermite.html @@ -0,0 +1,27 @@ +random_hermite in ndarray_linalg::generate - Rust + + + + + + +
pub fn random_hermite<A, S>(n: usize) -> ArrayBase<S, Ix2> where
    A: Scalar,
    S: DataOwned<Elem = A> + DataMut
Expand description

Random Hermite matrix

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.random_hpd.html b/ndarray_linalg/generate/fn.random_hpd.html new file mode 100644 index 00000000..f8109a88 --- /dev/null +++ b/ndarray_linalg/generate/fn.random_hpd.html @@ -0,0 +1,30 @@ +random_hpd in ndarray_linalg::generate - Rust + + + + + + +
pub fn random_hpd<A, S>(n: usize) -> ArrayBase<S, Ix2> where
    A: Scalar,
    S: DataOwned<Elem = A> + DataMut
Expand description

Random Hermite Positive-definite matrix

+
    +
  • Eigenvalue of matrix must be larger than 1 (thus non-singular)
  • +
+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.random_regular.html b/ndarray_linalg/generate/fn.random_regular.html new file mode 100644 index 00000000..79252f15 --- /dev/null +++ b/ndarray_linalg/generate/fn.random_regular.html @@ -0,0 +1,28 @@ +random_regular in ndarray_linalg::generate - Rust + + + + + + +
pub fn random_regular<A>(n: usize) -> Array2<A> where
    A: Scalar + Lapack
Expand description

Generate random regular matrix

+

Be sure that this it NOT a uniform distribution. Use it only for test purpose.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.random_unitary.html b/ndarray_linalg/generate/fn.random_unitary.html new file mode 100644 index 00000000..54bc3d7c --- /dev/null +++ b/ndarray_linalg/generate/fn.random_unitary.html @@ -0,0 +1,28 @@ +random_unitary in ndarray_linalg::generate - Rust + + + + + + +
pub fn random_unitary<A>(n: usize) -> Array2<A> where
    A: Scalar + Lapack
Expand description

Generate random unitary matrix using QR decomposition

+

Be sure that this it NOT a uniform distribution. Use it only for test purpose.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/fn.vstack.html b/ndarray_linalg/generate/fn.vstack.html new file mode 100644 index 00000000..bc100029 --- /dev/null +++ b/ndarray_linalg/generate/fn.vstack.html @@ -0,0 +1,27 @@ +vstack in ndarray_linalg::generate - Rust + + + + + + +
pub fn vstack<A, S>(xs: &[ArrayBase<S, Ix1>]) -> Result<Array<A, Ix2>> where
    A: Scalar,
    S: Data<Elem = A>, 
Expand description

stack vectors into matrix vertically

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/index.html b/ndarray_linalg/generate/index.html new file mode 100644 index 00000000..00e3c4f1 --- /dev/null +++ b/ndarray_linalg/generate/index.html @@ -0,0 +1,37 @@ +ndarray_linalg::generate - Rust + + + + + + +
Expand description

Generator functions for matrices

+

Functions

+

Hermite conjugate matrix

+

construct matrix from diag

+

stack vectors into matrix horizontally

+

Generate random array

+

Random Hermite matrix

+

Random Hermite Positive-definite matrix

+

Generate random regular matrix

+

Generate random unitary matrix using QR decomposition

+

stack vectors into matrix vertically

+
+ \ No newline at end of file diff --git a/ndarray_linalg/generate/sidebar-items.js b/ndarray_linalg/generate/sidebar-items.js new file mode 100644 index 00000000..d6237c21 --- /dev/null +++ b/ndarray_linalg/generate/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":[["conjugate","Hermite conjugate matrix"],["from_diag","construct matrix from diag"],["hstack","stack vectors into matrix horizontally"],["random","Generate random array"],["random_hermite","Random Hermite matrix"],["random_hpd","Random Hermite Positive-definite matrix"],["random_regular","Generate random regular matrix"],["random_unitary","Generate random unitary matrix using QR decomposition"],["vstack","stack vectors into matrix vertically"]]}; \ No newline at end of file diff --git a/ndarray_linalg/index.html b/ndarray_linalg/index.html new file mode 100644 index 00000000..bd26822e --- /dev/null +++ b/ndarray_linalg/index.html @@ -0,0 +1,100 @@ +ndarray_linalg - Rust + + + + + + +
Expand description

The ndarray-linalg crate provides linear algebra functionalities for ArrayBase, the n-dimensional array data structure provided by ndarray.

+

ndarray-linalg leverages LAPACK’s routines using the bindings provided by blas-lapack-rs/lapack.

+

Linear algebra methods

+ +

Naming Convention

+

Each routine is usually exposed as a trait, implemented by the relevant types.

+

For each routine there might be multiple “variants”: different traits corresponding to the different ownership possibilities of the array you intend to work on.

+

For example, if you are interested in the QR decomposition of a square matrix, you can use:

+
    +
  • QRSquare, if you hold an immutable reference (i.e. &self) to the matrix you want to decompose;
  • +
  • QRSquareInplace, if you hold a mutable reference (i.e. &mut self) to the matrix you want to decompose;
  • +
  • QRSquareInto, if you can pass the matrix you want to decompose by value (e.g. self).
  • +
+

Depending on the algorithm, each variant might require more or less copy operations of the underlying data.

+

Details are provided in the description of each routine.

+

Utilities

+ +

Re-exports

+
pub use crate::assert::*;
pub use crate::cholesky::*;
pub use crate::convert::*;
pub use crate::diagonal::*;
pub use crate::eig::*;
pub use crate::eigh::*;
pub use crate::generate::*;
pub use crate::inner::*;
pub use crate::layout::*;
pub use crate::least_squares::*;
pub use crate::norm::*;
pub use crate::operator::*;
pub use crate::opnorm::*;
pub use crate::qr::*;
pub use crate::solve::*;
pub use crate::solveh::*;
pub use crate::svd::*;
pub use crate::svddc::*;
pub use crate::trace::*;
pub use crate::triangular::*;
pub use crate::tridiagonal::*;
pub use crate::types::*;

Modules

+

Assertions for array

+

Cholesky decomposition of Hermitian (or real symmetric) positive definite matrices

+

utilities for convert array

+

Vector as a Diagonal matrix

+

Eigenvalue decomposition for non-symmetric square matrices

+

Eigendecomposition for Hermitian matrices.

+

Define Errors

+

Generator functions for matrices

+

Krylov subspace methods

+

Convert ndarray into LAPACK-compatible matrix format

+

Least Squares

+

Norm of vectors

+

Linear operator algebra

+

Operator norm

+

QR decomposition

+

Solve systems of linear equations and invert matrices

+

Solve Hermitian (or real symmetric) linear problems and invert Hermitian +(or real symmetric) matrices

+

Singular-value decomposition (SVD)

+

Singular-value decomposition (SVD) by divide-and-conquer (?gesdd)

+

Trace calculation

+

Methods for triangular matrices

+

Vectors as a Tridiagonal matrix +& +Methods for tridiagonal matrices

+

Basic types and their methods for linear algebra

+

Macros

+

Structs

+

Truncated eigenproblem solver

+

Truncated singular value decomposition

+

Enums

+

Find largest or smallest eigenvalues

+
+ \ No newline at end of file diff --git a/ndarray_linalg/inner/index.html b/ndarray_linalg/inner/index.html new file mode 100644 index 00000000..3dd30434 --- /dev/null +++ b/ndarray_linalg/inner/index.html @@ -0,0 +1,28 @@ +ndarray_linalg::inner - Rust + + + + + + +

Traits

+

Inner Product

+
+ \ No newline at end of file diff --git a/ndarray_linalg/inner/sidebar-items.js b/ndarray_linalg/inner/sidebar-items.js new file mode 100644 index 00000000..6d5ed55b --- /dev/null +++ b/ndarray_linalg/inner/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["InnerProduct","Inner Product"]]}; \ No newline at end of file diff --git a/ndarray_linalg/inner/trait.InnerProduct.html b/ndarray_linalg/inner/trait.InnerProduct.html new file mode 100644 index 00000000..81e8aaf6 --- /dev/null +++ b/ndarray_linalg/inner/trait.InnerProduct.html @@ -0,0 +1,33 @@ +InnerProduct in ndarray_linalg::inner - Rust + + + + + + +
pub trait InnerProduct {
+    type Elem: Scalar;
+
+    fn inner<S>(&self, rhs: &ArrayBase<S, Ix1>) -> Self::Elem
    where
        S: Data<Elem = Self::Elem>
; +}
Expand description

Inner Product

+

Differenct from Dot trait, this take complex conjugate of self elements

+

Required Associated Types

Required Methods

Inner product `(self.conjugate, rhs)

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/arnoldi/fn.arnoldi_householder.html b/ndarray_linalg/krylov/arnoldi/fn.arnoldi_householder.html new file mode 100644 index 00000000..10009e3c --- /dev/null +++ b/ndarray_linalg/krylov/arnoldi/fn.arnoldi_householder.html @@ -0,0 +1,27 @@ +arnoldi_householder in ndarray_linalg::krylov::arnoldi - Rust + + + + + + +
pub fn arnoldi_householder<A, S>(
    a: impl LinearOperator<Elem = A>,
    v: ArrayBase<S, Ix1>,
    tol: A::Real
) -> (Q<A>, H<A>) where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>, 
Expand description

Utility to execute Arnoldi iteration with Householder reflection

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/arnoldi/fn.arnoldi_mgs.html b/ndarray_linalg/krylov/arnoldi/fn.arnoldi_mgs.html new file mode 100644 index 00000000..36f5d30c --- /dev/null +++ b/ndarray_linalg/krylov/arnoldi/fn.arnoldi_mgs.html @@ -0,0 +1,27 @@ +arnoldi_mgs in ndarray_linalg::krylov::arnoldi - Rust + + + + + + +
pub fn arnoldi_mgs<A, S>(
    a: impl LinearOperator<Elem = A>,
    v: ArrayBase<S, Ix1>,
    tol: A::Real
) -> (Q<A>, H<A>) where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>, 
Expand description

Utility to execute Arnoldi iteration with modified Gram-Schmit orthogonalizer

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/arnoldi/index.html b/ndarray_linalg/krylov/arnoldi/index.html new file mode 100644 index 00000000..91f7f5fa --- /dev/null +++ b/ndarray_linalg/krylov/arnoldi/index.html @@ -0,0 +1,32 @@ +ndarray_linalg::krylov::arnoldi - Rust + + + + + + +
Expand description

Arnoldi iteration

+

Structs

+

Execute Arnoldi iteration as Rust iterator

+

Functions

+

Utility to execute Arnoldi iteration with Householder reflection

+

Utility to execute Arnoldi iteration with modified Gram-Schmit orthogonalizer

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/arnoldi/sidebar-items.js b/ndarray_linalg/krylov/arnoldi/sidebar-items.js new file mode 100644 index 00000000..496f6279 --- /dev/null +++ b/ndarray_linalg/krylov/arnoldi/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":[["arnoldi_householder","Utility to execute Arnoldi iteration with Householder reflection"],["arnoldi_mgs","Utility to execute Arnoldi iteration with modified Gram-Schmit orthogonalizer"]],"struct":[["Arnoldi","Execute Arnoldi iteration as Rust iterator"]]}; \ No newline at end of file diff --git a/ndarray_linalg/krylov/arnoldi/struct.Arnoldi.html b/ndarray_linalg/krylov/arnoldi/struct.Arnoldi.html new file mode 100644 index 00000000..86074c30 --- /dev/null +++ b/ndarray_linalg/krylov/arnoldi/struct.Arnoldi.html @@ -0,0 +1,164 @@ +Arnoldi in ndarray_linalg::krylov::arnoldi - Rust + + + + + + +
pub struct Arnoldi<A, S, F, Ortho> where
    A: Scalar,
    S: DataMut<Elem = A>,
    F: LinearOperator<Elem = A>,
    Ortho: Orthogonalizer<Elem = A>, 
{ /* private fields */ }
Expand description

Execute Arnoldi iteration as Rust iterator

+ +

Implementations

Create an Arnoldi iterator from any linear operator a

+

Dimension of Krylov subspace

+

Iterate until convergent

+

Trait Implementations

The type of the elements being iterated over.

+

Advances the iterator and returns the next value. Read more

+

Returns the bounds on the remaining length of the iterator. Read more

+

Consumes the iterator, counting the number of iterations and returning it. Read more

+

Consumes the iterator, returning the last element. Read more

+
🔬 This is a nightly-only experimental API. (iter_advance_by)

Advances the iterator by n elements. Read more

+

Returns the nth element of the iterator. Read more

+

Creates an iterator starting at the same point, but stepping by +the given amount at each iteration. Read more

+

Takes two iterators and creates a new iterator over both in sequence. Read more

+

‘Zips up’ two iterators into a single iterator of pairs. Read more

+
🔬 This is a nightly-only experimental API. (iter_intersperse)

Creates a new iterator which places a copy of separator between adjacent +items of the original iterator. Read more

+
🔬 This is a nightly-only experimental API. (iter_intersperse)

Creates a new iterator which places an item generated by separator +between adjacent items of the original iterator. Read more

+

Takes a closure and creates an iterator which calls that closure on each +element. Read more

+

Calls a closure on each element of an iterator. Read more

+

Creates an iterator which uses a closure to determine if an element +should be yielded. Read more

+

Creates an iterator that both filters and maps. Read more

+

Creates an iterator which gives the current iteration count as well as +the next value. Read more

+

Creates an iterator which can use the peek and peek_mut methods +to look at the next element of the iterator without consuming it. See +their documentation for more information. Read more

+

Creates an iterator that skips elements based on a predicate. Read more

+

Creates an iterator that yields elements based on a predicate. Read more

+

Creates an iterator that both yields elements based on a predicate and maps. Read more

+

Creates an iterator that skips the first n elements. Read more

+

Creates an iterator that yields the first n elements, or fewer +if the underlying iterator ends sooner. Read more

+

An iterator adapter similar to fold that holds internal state and +produces a new iterator. Read more

+

Creates an iterator that works like map, but flattens nested structure. Read more

+

Creates an iterator that flattens nested structure. Read more

+

Creates an iterator which ends after the first None. Read more

+

Does something with each element of an iterator, passing the value on. Read more

+

Borrows an iterator, rather than consuming it. Read more

+

Transforms an iterator into a collection. Read more

+
🔬 This is a nightly-only experimental API. (iterator_try_collect)

Fallibly transforms an iterator into a collection, short circuiting if +a failure is encountered. Read more

+
🔬 This is a nightly-only experimental API. (iter_collect_into)

Collects all the items from an iterator into a collection. Read more

+

Consumes an iterator, creating two collections from it. Read more

+
🔬 This is a nightly-only experimental API. (iter_partition_in_place)

Reorders the elements of this iterator in-place according to the given predicate, +such that all those that return true precede all those that return false. +Returns the number of true elements found. Read more

+
🔬 This is a nightly-only experimental API. (iter_is_partitioned)

Checks if the elements of this iterator are partitioned according to the given predicate, +such that all those that return true precede all those that return false. Read more

+

An iterator method that applies a function as long as it returns +successfully, producing a single, final value. Read more

+

An iterator method that applies a fallible function to each item in the +iterator, stopping at the first error and returning that error. Read more

+

Folds every element into an accumulator by applying an operation, +returning the final result. Read more

+

Reduces the elements to a single one, by repeatedly applying a reducing +operation. Read more

+
🔬 This is a nightly-only experimental API. (iterator_try_reduce)

Reduces the elements to a single one by repeatedly applying a reducing operation. If the +closure returns a failure, the failure is propagated back to the caller immediately. Read more

+

Tests if every element of the iterator matches a predicate. Read more

+

Tests if any element of the iterator matches a predicate. Read more

+

Searches for an element of an iterator that satisfies a predicate. Read more

+

Applies function to the elements of iterator and returns +the first non-none result. Read more

+
🔬 This is a nightly-only experimental API. (try_find)

Applies function to the elements of iterator and returns +the first true result or the first error. Read more

+

Searches for an element in an iterator, returning its index. Read more

+

Searches for an element in an iterator from the right, returning its +index. Read more

+

Returns the maximum element of an iterator. Read more

+

Returns the minimum element of an iterator. Read more

+

Returns the element that gives the maximum value from the +specified function. Read more

+

Returns the element that gives the maximum value with respect to the +specified comparison function. Read more

+

Returns the element that gives the minimum value from the +specified function. Read more

+

Returns the element that gives the minimum value with respect to the +specified comparison function. Read more

+

Reverses an iterator’s direction. Read more

+

Converts an iterator of pairs into a pair of containers. Read more

+

Creates an iterator which copies all of its elements. Read more

+

Creates an iterator which clones all of its elements. Read more

+

Repeats an iterator endlessly. Read more

+

Sums the elements of an iterator. Read more

+

Iterates over the entire iterator, multiplying all the elements Read more

+

Lexicographically compares the elements of this Iterator with those +of another. Read more

+
🔬 This is a nightly-only experimental API. (iter_order_by)

Lexicographically compares the elements of this Iterator with those +of another with respect to the specified comparison function. Read more

+

Lexicographically compares the elements of this Iterator with those +of another. Read more

+
🔬 This is a nightly-only experimental API. (iter_order_by)

Lexicographically compares the elements of this Iterator with those +of another with respect to the specified comparison function. Read more

+

Determines if the elements of this Iterator are equal to those of +another. Read more

+
🔬 This is a nightly-only experimental API. (iter_order_by)

Determines if the elements of this Iterator are equal to those of +another with respect to the specified equality function. Read more

+

Determines if the elements of this Iterator are unequal to those of +another. Read more

+

Determines if the elements of this Iterator are lexicographically +less than those of another. Read more

+

Determines if the elements of this Iterator are lexicographically +less or equal to those of another. Read more

+

Determines if the elements of this Iterator are lexicographically +greater than those of another. Read more

+

Determines if the elements of this Iterator are lexicographically +greater than or equal to those of another. Read more

+
🔬 This is a nightly-only experimental API. (is_sorted)

Checks if the elements of this iterator are sorted. Read more

+
🔬 This is a nightly-only experimental API. (is_sorted)

Checks if the elements of this iterator are sorted using the given comparator function. Read more

+
🔬 This is a nightly-only experimental API. (is_sorted)

Checks if the elements of this iterator are sorted using the given key extraction +function. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type of the elements being iterated over.

+

Which kind of iterator are we turning this into?

+

Creates an iterator from a value. Read more

+

Choose one element at random from the iterator. Read more

+

Choose one element at random from the iterator. Read more

+

Collects values at random from the iterator into a supplied buffer +until that buffer is filled. Read more

+

Collects amount values at random from the iterator into a vector. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/enum.AppendResult.html b/ndarray_linalg/krylov/enum.AppendResult.html new file mode 100644 index 00000000..60da06a8 --- /dev/null +++ b/ndarray_linalg/krylov/enum.AppendResult.html @@ -0,0 +1,40 @@ +AppendResult in ndarray_linalg::krylov - Rust + + + + + + +
pub enum AppendResult<A> {
+    Added(Coefficients<A>),
+    Dependent(Coefficients<A>),
+}

Variants

Added(Coefficients<A>)

Dependent(Coefficients<A>)

Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/enum.Strategy.html b/ndarray_linalg/krylov/enum.Strategy.html new file mode 100644 index 00000000..9dc90556 --- /dev/null +++ b/ndarray_linalg/krylov/enum.Strategy.html @@ -0,0 +1,58 @@ +Strategy in ndarray_linalg::krylov - Rust + + + + + + +
pub enum Strategy {
+    Terminate,
+    Skip,
+    Full,
+}
Expand description

Strategy for linearly dependent vectors appearing in iterative QR decomposition

+

Variants

Terminate

Terminate iteration if dependent vector comes

+

Skip

Skip dependent vector

+

Full

Orthogonalize dependent vector without adding to Q, +i.e. R must be non-square like following:

+
x x x x x
+0 x x x x
+0 0 0 x x
+0 0 0 0 x

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/fn.qr.html b/ndarray_linalg/krylov/fn.qr.html new file mode 100644 index 00000000..89870b98 --- /dev/null +++ b/ndarray_linalg/krylov/fn.qr.html @@ -0,0 +1,27 @@ +qr in ndarray_linalg::krylov - Rust + + + + + + +
pub fn qr<A, S>(
    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
    ortho: impl Orthogonalizer<Elem = A>,
    strategy: Strategy
) -> (Q<A>, R<A>) where
    A: Scalar + Lapack,
    S: Data<Elem = A>, 
Expand description

Online QR decomposition using arbitrary orthogonalizer

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/householder/fn.calc_reflector.html b/ndarray_linalg/krylov/householder/fn.calc_reflector.html new file mode 100644 index 00000000..c2cb476c --- /dev/null +++ b/ndarray_linalg/krylov/householder/fn.calc_reflector.html @@ -0,0 +1,27 @@ +calc_reflector in ndarray_linalg::krylov::householder - Rust + + + + + + +
pub fn calc_reflector<A, S>(x: &mut ArrayBase<S, Ix1>) where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>, 
Expand description

Calc a reflactor w from a vector x

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/householder/fn.householder.html b/ndarray_linalg/krylov/householder/fn.householder.html new file mode 100644 index 00000000..018e01f3 --- /dev/null +++ b/ndarray_linalg/krylov/householder/fn.householder.html @@ -0,0 +1,27 @@ +householder in ndarray_linalg::krylov::householder - Rust + + + + + + +
pub fn householder<A, S>(
    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
    dim: usize,
    rtol: A::Real,
    strategy: Strategy
) -> (Q<A>, R<A>) where
    A: Scalar + Lapack,
    S: Data<Elem = A>, 
Expand description

Online QR decomposition using Householder reflection

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/householder/fn.reflect.html b/ndarray_linalg/krylov/householder/fn.reflect.html new file mode 100644 index 00000000..b7edfbaf --- /dev/null +++ b/ndarray_linalg/krylov/householder/fn.reflect.html @@ -0,0 +1,31 @@ +reflect in ndarray_linalg::krylov::householder - Rust + + + + + + +
pub fn reflect<A, S1, S2>(w: &ArrayBase<S1, Ix1>, a: &mut ArrayBase<S2, Ix1>) where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>, 
Expand description

Take a reflection P = I - 2ww^T

+

Panic

+
    +
  • if the size of w and a mismaches
  • +
+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/householder/index.html b/ndarray_linalg/krylov/householder/index.html new file mode 100644 index 00000000..7bf89859 --- /dev/null +++ b/ndarray_linalg/krylov/householder/index.html @@ -0,0 +1,36 @@ +ndarray_linalg::krylov::householder - Rust + + + + + + +
Expand description

Householder reflection

+ +

Structs

+

Iterative orthogonalizer using Householder reflection

+

Functions

+

Calc a reflactor w from a vector x

+

Online QR decomposition using Householder reflection

+

Take a reflection P = I - 2ww^T

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/householder/sidebar-items.js b/ndarray_linalg/krylov/householder/sidebar-items.js new file mode 100644 index 00000000..b0d24559 --- /dev/null +++ b/ndarray_linalg/krylov/householder/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":[["calc_reflector","Calc a reflactor `w` from a vector `x`"],["householder","Online QR decomposition using Householder reflection"],["reflect","Take a reflection `P = I - 2ww^T`"]],"struct":[["Householder","Iterative orthogonalizer using Householder reflection"]]}; \ No newline at end of file diff --git a/ndarray_linalg/krylov/householder/struct.Householder.html b/ndarray_linalg/krylov/householder/struct.Householder.html new file mode 100644 index 00000000..d0fd8684 --- /dev/null +++ b/ndarray_linalg/krylov/householder/struct.Householder.html @@ -0,0 +1,57 @@ +Householder in ndarray_linalg::krylov::householder - Rust + + + + + + +
pub struct Householder<A: Scalar> { /* private fields */ }
Expand description

Iterative orthogonalizer using Householder reflection

+

Implementations

Create a new orthogonalizer

+

Take forward reflection P = P_l ... P_1

+

Take backward reflection P = P_1 ... P_l

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Dimension of input array

+

Number of cached basis

+

Decompose given vector into the span of current basis and +its tangent space Read more

+

Calculate the coefficient to the current basis basis Read more

+

Add new vector if the residual is larger than relative tolerance, +and return the residual vector Read more

+

Add new vector if the residual is larger than relative tolerance

+

Get Q-matrix of generated basis

+

check if the basis spans entire space

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/index.html b/ndarray_linalg/krylov/index.html new file mode 100644 index 00000000..7a1fde33 --- /dev/null +++ b/ndarray_linalg/krylov/index.html @@ -0,0 +1,43 @@ +ndarray_linalg::krylov - Rust + + + + + + +
Expand description

Krylov subspace methods

+

Re-exports

+
pub use arnoldi::arnoldi_householder;
pub use arnoldi::arnoldi_mgs;
pub use arnoldi::Arnoldi;
pub use householder::householder;
pub use householder::Householder;
pub use mgs::mgs;
pub use mgs::MGS;

Modules

+

Arnoldi iteration

+

Householder reflection

+

Modified Gram-Schmit orthogonalizer

+

Enums

+

Strategy for linearly dependent vectors appearing in iterative QR decomposition

+

Traits

+

Trait for creating orthogonal basis from iterator of arrays

+

Functions

+

Online QR decomposition using arbitrary orthogonalizer

+

Type Definitions

+

Array type for coefficients to the current basis

+

H-matrix

+

Q-matrix

+

R-matrix

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/mgs/fn.mgs.html b/ndarray_linalg/krylov/mgs/fn.mgs.html new file mode 100644 index 00000000..86eb90df --- /dev/null +++ b/ndarray_linalg/krylov/mgs/fn.mgs.html @@ -0,0 +1,27 @@ +mgs in ndarray_linalg::krylov::mgs - Rust + + + + + + +
pub fn mgs<A, S>(
    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
    dim: usize,
    rtol: A::Real,
    strategy: Strategy
) -> (Q<A>, R<A>) where
    A: Scalar + Lapack,
    S: Data<Elem = A>, 
Expand description

Online QR decomposition using modified Gram-Schmit algorithm

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/mgs/index.html b/ndarray_linalg/krylov/mgs/index.html new file mode 100644 index 00000000..d8484a36 --- /dev/null +++ b/ndarray_linalg/krylov/mgs/index.html @@ -0,0 +1,31 @@ +ndarray_linalg::krylov::mgs - Rust + + + + + + +
Expand description

Modified Gram-Schmit orthogonalizer

+

Structs

+

Iterative orthogonalizer using modified Gram-Schmit procedure

+

Functions

+

Online QR decomposition using modified Gram-Schmit algorithm

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/mgs/sidebar-items.js b/ndarray_linalg/krylov/mgs/sidebar-items.js new file mode 100644 index 00000000..d7806319 --- /dev/null +++ b/ndarray_linalg/krylov/mgs/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":[["mgs","Online QR decomposition using modified Gram-Schmit algorithm"]],"struct":[["MGS","Iterative orthogonalizer using modified Gram-Schmit procedure"]]}; \ No newline at end of file diff --git a/ndarray_linalg/krylov/mgs/struct.MGS.html b/ndarray_linalg/krylov/mgs/struct.MGS.html new file mode 100644 index 00000000..c15e16c8 --- /dev/null +++ b/ndarray_linalg/krylov/mgs/struct.MGS.html @@ -0,0 +1,55 @@ +MGS in ndarray_linalg::krylov::mgs - Rust + + + + + + +
pub struct MGS<A: Scalar> { /* private fields */ }
Expand description

Iterative orthogonalizer using modified Gram-Schmit procedure

+

Implementations

Create an empty orthogonalizer

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Dimension of input array

+

Number of cached basis

+

Decompose given vector into the span of current basis and +its tangent space Read more

+

Calculate the coefficient to the current basis basis Read more

+

Add new vector if the residual is larger than relative tolerance

+

Add new vector if the residual is larger than relative tolerance, +and return the residual vector Read more

+

Get Q-matrix of generated basis

+

check if the basis spans entire space

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/sidebar-items.js b/ndarray_linalg/krylov/sidebar-items.js new file mode 100644 index 00000000..a90189cd --- /dev/null +++ b/ndarray_linalg/krylov/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["AppendResult",""],["Strategy","Strategy for linearly dependent vectors appearing in iterative QR decomposition"]],"fn":[["qr","Online QR decomposition using arbitrary orthogonalizer"]],"mod":[["arnoldi","Arnoldi iteration"],["householder","Householder reflection"],["mgs","Modified Gram-Schmit orthogonalizer"]],"trait":[["Orthogonalizer","Trait for creating orthogonal basis from iterator of arrays"]],"type":[["Coefficients","Array type for coefficients to the current basis"],["H","H-matrix"],["Q","Q-matrix"],["R","R-matrix"]]}; \ No newline at end of file diff --git a/ndarray_linalg/krylov/trait.Orthogonalizer.html b/ndarray_linalg/krylov/trait.Orthogonalizer.html new file mode 100644 index 00000000..86b0ac0b --- /dev/null +++ b/ndarray_linalg/krylov/trait.Orthogonalizer.html @@ -0,0 +1,78 @@ +Orthogonalizer in ndarray_linalg::krylov - Rust + + + + + + +
pub trait Orthogonalizer {
+    type Elem: Scalar;
+
+    fn dim(&self) -> usize;
+    fn len(&self) -> usize;
+    fn tolerance(&self) -> <Self::Elem as Scalar>::Real;
+    fn decompose<S>(
        &self,
        a: &mut ArrayBase<S, Ix1>
    ) -> Coefficients<Self::Elem>
    where
        S: DataMut<Elem = Self::Elem>
; + fn coeff<S>(&self, a: ArrayBase<S, Ix1>) -> Coefficients<Self::Elem>
    where
        S: Data<Elem = Self::Elem>
; + fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> AppendResult<Self::Elem>
    where
        S: Data<Elem = Self::Elem>
; + fn div_append<S>(
        &mut self,
        a: &mut ArrayBase<S, Ix1>
    ) -> AppendResult<Self::Elem>
    where
        S: DataMut<Elem = Self::Elem>
; + fn get_q(&self) -> Q<Self::Elem>; + + fn is_full(&self) -> bool { ... } + fn is_empty(&self) -> bool { ... } +}
Expand description

Trait for creating orthogonal basis from iterator of arrays

+

Panic

+
    +
  • if the size of the input array mismatches to the dimension
  • +
+

Example

+
let mut mgs = MGS::new(3, 1e-9);
+let coef = mgs.append(array![0.0, 1.0, 0.0]).into_coeff();
+close_l2(&coef, &array![1.0], 1e-9);
+
+let coef = mgs.append(array![1.0, 1.0, 0.0]).into_coeff();
+close_l2(&coef, &array![1.0, 1.0], 1e-9);
+
+// Fail if the vector is linearly dependent
+assert!(mgs.append(array![1.0, 2.0, 0.0]).is_dependent());
+
+// You can get coefficients of dependent vector
+if let AppendResult::Dependent(coef) = mgs.append(array![1.0, 2.0, 0.0]) {
+    close_l2(&coef, &array![2.0, 1.0, 0.0], 1e-9);
+}
+

Required Associated Types

Required Methods

Dimension of input array

+

Number of cached basis

+

Decompose given vector into the span of current basis and +its tangent space

+
    +
  • a becomes the tangent vector
  • +
  • The Coefficients to the current basis is returned.
  • +
+

Calculate the coefficient to the current basis basis

+
    +
  • This will be faster than decompose because the construction of the residual vector may +requires more Calculation
  • +
+

Add new vector if the residual is larger than relative tolerance

+

Add new vector if the residual is larger than relative tolerance, +and return the residual vector

+

Get Q-matrix of generated basis

+

Provided Methods

check if the basis spans entire space

+

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/type.Coefficients.html b/ndarray_linalg/krylov/type.Coefficients.html new file mode 100644 index 00000000..a53f36d8 --- /dev/null +++ b/ndarray_linalg/krylov/type.Coefficients.html @@ -0,0 +1,31 @@ +Coefficients in ndarray_linalg::krylov - Rust + + + + + + +
pub type Coefficients<A> = Array1<A>;
Expand description

Array type for coefficients to the current basis

+
    +
  • The length must be self.len() + 1
  • +
  • Last component is the residual norm
  • +
+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/type.H.html b/ndarray_linalg/krylov/type.H.html new file mode 100644 index 00000000..32e1f49b --- /dev/null +++ b/ndarray_linalg/krylov/type.H.html @@ -0,0 +1,31 @@ +H in ndarray_linalg::krylov - Rust + + + + + + +
+

Type Definition ndarray_linalg::krylov::H

source · []
pub type H<A> = Array2<A>;
Expand description

H-matrix

+
    +
  • Maybe NOT square
  • +
  • Hessenberg matrix
  • +
+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/type.Q.html b/ndarray_linalg/krylov/type.Q.html new file mode 100644 index 00000000..f31b84fd --- /dev/null +++ b/ndarray_linalg/krylov/type.Q.html @@ -0,0 +1,31 @@ +Q in ndarray_linalg::krylov - Rust + + + + + + +
+

Type Definition ndarray_linalg::krylov::Q

source · []
pub type Q<A> = Array2<A>;
Expand description

Q-matrix

+
    +
  • Maybe NOT square
  • +
  • Unitary for existing columns
  • +
+
+ \ No newline at end of file diff --git a/ndarray_linalg/krylov/type.R.html b/ndarray_linalg/krylov/type.R.html new file mode 100644 index 00000000..c6ec318b --- /dev/null +++ b/ndarray_linalg/krylov/type.R.html @@ -0,0 +1,31 @@ +R in ndarray_linalg::krylov - Rust + + + + + + +
+

Type Definition ndarray_linalg::krylov::R

source · []
pub type R<A> = Array2<A>;
Expand description

R-matrix

+
    +
  • Maybe NOT square
  • +
  • Upper triangle
  • +
+
+ \ No newline at end of file diff --git a/ndarray_linalg/layout/enum.MatrixLayout.html b/ndarray_linalg/layout/enum.MatrixLayout.html new file mode 100644 index 00000000..7ab7db72 --- /dev/null +++ b/ndarray_linalg/layout/enum.MatrixLayout.html @@ -0,0 +1,67 @@ +MatrixLayout in ndarray_linalg::layout - Rust + + + + + + +
pub enum MatrixLayout {
+    C {
+        row: i32,
+        lda: i32,
+    },
+    F {
+        col: i32,
+        lda: i32,
+    },
+}

Variants

C

Fields

row: i32
lda: i32

F

Fields

col: i32
lda: i32

Implementations

Transpose without changing memory representation

+

C-contigious row=2, lda=3

+
[[1, 2, 3]
+ [4, 5, 6]]
+

and F-contigious col=2, lda=3

+
[[1, 4]
+ [2, 5]
+ [3, 6]]
+

have same memory representation [1, 2, 3, 4, 5, 6], and this toggles them.

+ +
let layout = MatrixLayout::C { row: 2, lda: 3 };
+assert_eq!(layout.t(), MatrixLayout::F { col: 2, lda: 3 });
+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/layout/index.html b/ndarray_linalg/layout/index.html new file mode 100644 index 00000000..c75710e0 --- /dev/null +++ b/ndarray_linalg/layout/index.html @@ -0,0 +1,29 @@ +ndarray_linalg::layout - Rust + + + + + + +
Expand description

Convert ndarray into LAPACK-compatible matrix format

+

Enums

+

Traits

+
+ \ No newline at end of file diff --git a/ndarray_linalg/layout/sidebar-items.js b/ndarray_linalg/layout/sidebar-items.js new file mode 100644 index 00000000..85453d37 --- /dev/null +++ b/ndarray_linalg/layout/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["MatrixLayout",""]],"trait":[["AllocatedArray",""],["AllocatedArrayMut",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/layout/trait.AllocatedArray.html b/ndarray_linalg/layout/trait.AllocatedArray.html new file mode 100644 index 00000000..48dc53fc --- /dev/null +++ b/ndarray_linalg/layout/trait.AllocatedArray.html @@ -0,0 +1,34 @@ +AllocatedArray in ndarray_linalg::layout - Rust + + + + + + +
pub trait AllocatedArray {
+    type Elem;
+
+    fn layout(&self) -> Result<MatrixLayout>;
+    fn square_layout(&self) -> Result<MatrixLayout>;
+    fn ensure_square(&self) -> Result<()>;
+    fn as_allocated(&self) -> Result<&[Self::Elem]>;
+}

Required Associated Types

Required Methods

Returns Ok iff the matrix is square (without computing the layout).

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/layout/trait.AllocatedArrayMut.html b/ndarray_linalg/layout/trait.AllocatedArrayMut.html new file mode 100644 index 00000000..6456e29e --- /dev/null +++ b/ndarray_linalg/layout/trait.AllocatedArrayMut.html @@ -0,0 +1,28 @@ +AllocatedArrayMut in ndarray_linalg::layout - Rust + + + + + + +
pub trait AllocatedArrayMut: AllocatedArray {
+    fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
+}

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/least_squares/index.html b/ndarray_linalg/least_squares/index.html new file mode 100644 index 00000000..fc502278 --- /dev/null +++ b/ndarray_linalg/least_squares/index.html @@ -0,0 +1,86 @@ +ndarray_linalg::least_squares - Rust + + + + + + +
Expand description

Least Squares

+

Compute a least-squares solution to the equation Ax = b. +Compute a vector x such that the 2-norm |b - A x| is minimized.

+

Finding the least squares solutions is implemented as traits, meaning +that to solve A x = b for a matrix A and a RHS b, we call +let result = A.least_squares(&b);. This returns a result of +type LeastSquaresResult, the solution for the least square problem +is in result.solution.

+

There are three traits, LeastSquaresSvd with the method least_squares, +which operates on immutable references, LeastSquaresInto with the method +least_squares_into, which takes ownership over both the array A and the +RHS b and LeastSquaresSvdInPlace with the method least_squares_in_place, +which operates on mutable references for A and b and destroys these when +solving the least squares problem. LeastSquaresSvdInto and +LeastSquaresSvdInPlace avoid an extra allocation for A and b which +LeastSquaresSvd has do perform to preserve the values in A and b.

+

All methods use the Lapacke family of methods *gelsd which solves the least +squares problem using the SVD with a divide-and-conquer strategy.

+

The traits are implemented for value types f32, f64, c32 and c64 +and vector or matrix right-hand-sides (ArrayBase<S, Ix1> or ArrayBase<S, Ix2>).

+

Example

+
use approx::AbsDiffEq; // for abs_diff_eq
+use ndarray::{array, Array1, Array2};
+use ndarray_linalg::{LeastSquaresSvd, LeastSquaresSvdInto, LeastSquaresSvdInPlace};
+
+let a: Array2<f64> = array![
+    [1., 1., 1.],
+    [2., 3., 4.],
+    [3., 5., 2.],
+    [4., 2., 5.],
+    [5., 4., 3.]
+];
+// solving for a single right-hand side
+let b: Array1<f64> = array![-10., 12., 14., 16., 18.];
+let expected: Array1<f64> = array![2., 1., 1.];
+let result = a.least_squares(&b).unwrap();
+assert!(result.solution.abs_diff_eq(&expected, 1e-12));
+
+// solving for two right-hand sides at once
+let b_2: Array2<f64> =
+    array![[-10., -3.], [12., 14.], [14., 12.], [16., 16.], [18., 16.]];
+let expected_2: Array2<f64> = array![[2., 1.], [1., 1.], [1., 2.]];
+let result_2 = a.least_squares(&b_2).unwrap();
+assert!(result_2.solution.abs_diff_eq(&expected_2, 1e-12));
+
+// using `least_squares_in_place` which overwrites its arguments
+let mut a_3 = a.clone();
+let mut b_3 = b.clone();
+let result_3 = a_3.least_squares_in_place(&mut b_3).unwrap();
+
+// using `least_squares_into` which consumes its arguments
+let result_4 = a.least_squares_into(b).unwrap();
+// `a` and `b` have been moved, no longer valid
+

Structs

+

Result of a LeastSquares computation

+

Traits

+

Solve least squares for immutable references

+

Solve least squares for mutable references, overwriting +the input fields in the process

+

Solve least squares for owned matrices

+
+ \ No newline at end of file diff --git a/ndarray_linalg/least_squares/sidebar-items.js b/ndarray_linalg/least_squares/sidebar-items.js new file mode 100644 index 00000000..9ee4107c --- /dev/null +++ b/ndarray_linalg/least_squares/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":[["LeastSquaresResult","Result of a LeastSquares computation"]],"trait":[["LeastSquaresSvd","Solve least squares for immutable references"],["LeastSquaresSvdInPlace","Solve least squares for mutable references, overwriting the input fields in the process"],["LeastSquaresSvdInto","Solve least squares for owned matrices"]]}; \ No newline at end of file diff --git a/ndarray_linalg/least_squares/struct.LeastSquaresResult.html b/ndarray_linalg/least_squares/struct.LeastSquaresResult.html new file mode 100644 index 00000000..c84045d6 --- /dev/null +++ b/ndarray_linalg/least_squares/struct.LeastSquaresResult.html @@ -0,0 +1,63 @@ +LeastSquaresResult in ndarray_linalg::least_squares - Rust + + + + + + +
pub struct LeastSquaresResult<E: Scalar, I: Dimension> {
+    pub singular_values: Array1<E::Real>,
+    pub solution: Array<E, I>,
+    pub rank: i32,
+    pub residual_sum_of_squares: Option<Array<E::Real, I::Smaller>>,
+}
Expand description

Result of a LeastSquares computation

+

Takes two type parameters, E, the element type of the matrix +(one of f32, f64, c32 or c64) and I, the dimension of +b in the equation Ax = b (one of Ix1 or Ix2). If I is Ix1, +the right-hand-side (RHS) is a n x 1 column vector and the solution +is a m x 1 column vector. If I is Ix2, the RHS is a n x k matrix +(which can be seen as solving Ax = b k times for different b) and +the solution is a m x k matrix.

+

Fields

singular_values: Array1<E::Real>

The singular values of the matrix A in Ax = b

+
solution: Array<E, I>

The solution vector or matrix x which is the best +solution to Ax = b, i.e. minimizing the 2-norm ||b - Ax||

+
rank: i32

The rank of the matrix A in Ax = b

+
residual_sum_of_squares: Option<Array<E::Real, I::Smaller>>

If n < m and rank(A) == n, the sum of squares +If b is a (m x 1) vector, this is a 0-dimensional array (single value) +If b is a (m x k) matrix, this is a (k x 1) column vector

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/least_squares/trait.LeastSquaresSvd.html b/ndarray_linalg/least_squares/trait.LeastSquaresSvd.html new file mode 100644 index 00000000..2fd38867 --- /dev/null +++ b/ndarray_linalg/least_squares/trait.LeastSquaresSvd.html @@ -0,0 +1,55 @@ +LeastSquaresSvd in ndarray_linalg::least_squares - Rust + + + + + + +
pub trait LeastSquaresSvd<D, E, I> where
    D: Data<Elem = E>,
    E: Scalar + Lapack,
    I: Dimension
{ + fn least_squares(
        &self,
        rhs: &ArrayBase<D, I>
    ) -> Result<LeastSquaresResult<E, I>>; +}
Expand description

Solve least squares for immutable references

+

Required Methods

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(&rhs). A and rhs +are unchanged.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Implementations on Foreign Types

Solve least squares for immutable references and a single +column vector as a right-hand side. +E is one of f32, f64, c32, c64. D1, D2 can be any +valid representation for ArrayBase (over E).

+

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(&rhs), where rhs is a +single column vector. A and rhs are unchanged.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Solve least squares for immutable references and matrix +(=mulitipe vectors) as a right-hand side. +E is one of f32, f64, c32, c64. D1, D2 can be any +valid representation for ArrayBase (over E).

+

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(&rhs), where rhs is +matrix. A and rhs are unchanged.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/least_squares/trait.LeastSquaresSvdInPlace.html b/ndarray_linalg/least_squares/trait.LeastSquaresSvdInPlace.html new file mode 100644 index 00000000..6c797bf4 --- /dev/null +++ b/ndarray_linalg/least_squares/trait.LeastSquaresSvdInPlace.html @@ -0,0 +1,59 @@ +LeastSquaresSvdInPlace in ndarray_linalg::least_squares - Rust + + + + + + +
pub trait LeastSquaresSvdInPlace<D, E, I> where
    D: Data<Elem = E>,
    E: Scalar + Lapack,
    I: Dimension
{ + fn least_squares_in_place(
        &mut self,
        rhs: &mut ArrayBase<D, I>
    ) -> Result<LeastSquaresResult<E, I>>; +}
Expand description

Solve least squares for mutable references, overwriting +the input fields in the process

+

Required Methods

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(&mut rhs), overwriting both A +and rhs. This uses the memory location of A and +rhs, which avoids some extra memory allocations.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Implementations on Foreign Types

Solve least squares for mutable references and a vector +as a right-hand side. Both values are overwritten in the +call.

+

E is one of f32, f64, c32, c64. D1, D2 can be any +valid representation for ArrayBase (over E).

+

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(rhs), where rhs is a +vector. A and rhs are overwritten in the call.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Solve least squares for mutable references and a matrix +as a right-hand side. Both values are overwritten in the +call.

+

E is one of f32, f64, c32, c64. D1, D2 can be any +valid representation for ArrayBase (over E).

+

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(rhs), where rhs is a +matrix. A and rhs are overwritten in the call.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/least_squares/trait.LeastSquaresSvdInto.html b/ndarray_linalg/least_squares/trait.LeastSquaresSvdInto.html new file mode 100644 index 00000000..01c64b98 --- /dev/null +++ b/ndarray_linalg/least_squares/trait.LeastSquaresSvdInto.html @@ -0,0 +1,58 @@ +LeastSquaresSvdInto in ndarray_linalg::least_squares - Rust + + + + + + +
pub trait LeastSquaresSvdInto<D, E, I> where
    D: Data<Elem = E>,
    E: Scalar + Lapack,
    I: Dimension
{ + fn least_squares_into(
        self,
        rhs: ArrayBase<D, I>
    ) -> Result<LeastSquaresResult<E, I>>; +}
Expand description

Solve least squares for owned matrices

+

Required Methods

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(rhs), consuming both A +and rhs. This uses the memory location of A and +rhs, which avoids some extra memory allocations.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Implementations on Foreign Types

Solve least squares for owned values and a single +column vector as a right-hand side. The matrix and the RHS +vector are consumed.

+

E is one of f32, f64, c32, c64. D can be any +valid representation for ArrayBase.

+

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(rhs), where rhs is a +single column vector. A and rhs are consumed.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Solve least squares for owned values and a matrix +as a right-hand side. The matrix and the RHS matrix +are consumed.

+

E is one of f32, f64, c32, c64. D1, D2 can be any +valid representation for ArrayBase (over E).

+

Solve a least squares problem of the form Ax = rhs +by calling A.least_squares(rhs), where rhs is a +matrix. A and rhs are consumed.

+

A and rhs must have the same layout, i.e. they must +be both either row- or column-major format, otherwise a +IncompatibleShape error is raised.

+

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/eig/struct.TruncatedEig.html b/ndarray_linalg/lobpcg/eig/struct.TruncatedEig.html new file mode 100644 index 00000000..dcd1cbf4 --- /dev/null +++ b/ndarray_linalg/lobpcg/eig/struct.TruncatedEig.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../ndarray_linalg/lobpcg/struct.TruncatedEig.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/enum.LobpcgResult.html b/ndarray_linalg/lobpcg/enum.LobpcgResult.html new file mode 100644 index 00000000..51f3fe2a --- /dev/null +++ b/ndarray_linalg/lobpcg/enum.LobpcgResult.html @@ -0,0 +1,48 @@ +LobpcgResult in ndarray_linalg::lobpcg - Rust + + + + + + +
pub enum LobpcgResult<A> {
+    Ok(Array1<A>, Array2<A>, Vec<A>),
+    Err(Array1<A>, Array2<A>, Vec<A>, LinalgError),
+    NoResult(LinalgError),
+}
Expand description

The result of the eigensolver

+

In the best case the eigensolver has converged with a result better than the given threshold, +then a LobpcgResult::Ok gives the eigenvalues, eigenvectors and norms. If an error ocurred +during the process, it is returned in LobpcgResult::Err, but the best result is still returned, +as it could be usable. If there is no result at all, then LobpcgResult::NoResult is returned. +This happens if the algorithm fails in an early stage, for example if the matrix A is not SPD

+

Variants

Ok(Array1<A>, Array2<A>, Vec<A>)

Err(Array1<A>, Array2<A>, Vec<A>, LinalgError)

NoResult(LinalgError)

Trait Implementations

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/enum.TruncatedOrder.html b/ndarray_linalg/lobpcg/enum.TruncatedOrder.html new file mode 100644 index 00000000..933933c5 --- /dev/null +++ b/ndarray_linalg/lobpcg/enum.TruncatedOrder.html @@ -0,0 +1,47 @@ +TruncatedOrder in ndarray_linalg::lobpcg - Rust + + + + + + +
pub enum TruncatedOrder {
+    Largest,
+    Smallest,
+}
Expand description

Find largest or smallest eigenvalues

+

Variants

Largest

Smallest

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/fn.lobpcg.html b/ndarray_linalg/lobpcg/fn.lobpcg.html new file mode 100644 index 00000000..3bd59f53 --- /dev/null +++ b/ndarray_linalg/lobpcg/fn.lobpcg.html @@ -0,0 +1,46 @@ +lobpcg in ndarray_linalg::lobpcg - Rust + + + + + + +
pub fn lobpcg<A: Float + Scalar + Lapack + ScalarOperand + PartialOrd + Default, F: Fn(ArrayView2<'_, A>) -> Array2<A>, G: Fn(ArrayViewMut2<'_, A>)>(
    a: F,
    x: Array2<A>,
    m: G,
    y: Option<Array2<A>>,
    tol: f32,
    maxiter: usize,
    order: Order
) -> LobpcgResult<A>
Expand description

Eigenvalue solver for large symmetric positive definite (SPD) eigenproblems

+

Arguments

+
    +
  • a - An operator defining the problem, usually a sparse (sometimes also dense) matrix +multiplication. Also called the “stiffness matrix”.
  • +
  • x - Initial approximation of the k eigenvectors. If a has shape=(n,n), then x should +have shape=(n,k).
  • +
  • m - Preconditioner to a, by default the identity matrix. Should approximate the inverse +of a.
  • +
  • y - Constraints of (n,size_y), iterations are performed in the orthogonal complement of the +column-space of y. It must be full rank.
  • +
  • tol - The tolerance values defines at which point the solver stops the optimization. The approximation +of a eigenvalue stops when then l2-norm of the residual is below this threshold.
  • +
  • maxiter - The maximal number of iterations
  • +
  • order - Whether to solve for the largest or lowest eigenvalues
  • +
+

The function returns an LobpcgResult with the eigenvalue/eigenvector and achieved residual norm +for it. All iterations are tracked and the optimal solution returned. In case of an error a +special variant LobpcgResult::NotConverged additionally carries the error. This can happen when +the precision of the matrix is too low (switch then from f32 to f64 for example).

+
+ \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/index.html b/ndarray_linalg/lobpcg/index.html new file mode 100644 index 00000000..a50f6325 --- /dev/null +++ b/ndarray_linalg/lobpcg/index.html @@ -0,0 +1,34 @@ +ndarray_linalg::lobpcg - Rust + + + + + + +

Structs

+

Truncated eigenproblem solver

+

Truncated singular value decomposition

+

Enums

+

The result of the eigensolver

+

Find largest or smallest eigenvalues

+

Functions

+

Eigenvalue solver for large symmetric positive definite (SPD) eigenproblems

+
+ \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/lobpcg/enum.LobpcgResult.html b/ndarray_linalg/lobpcg/lobpcg/enum.LobpcgResult.html new file mode 100644 index 00000000..c78e4ced --- /dev/null +++ b/ndarray_linalg/lobpcg/lobpcg/enum.LobpcgResult.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../ndarray_linalg/lobpcg/enum.LobpcgResult.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/lobpcg/enum.Order.html b/ndarray_linalg/lobpcg/lobpcg/enum.Order.html new file mode 100644 index 00000000..e70b1615 --- /dev/null +++ b/ndarray_linalg/lobpcg/lobpcg/enum.Order.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../ndarray_linalg/lobpcg/enum.TruncatedOrder.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/lobpcg/fn.lobpcg.html b/ndarray_linalg/lobpcg/lobpcg/fn.lobpcg.html new file mode 100644 index 00000000..05206324 --- /dev/null +++ b/ndarray_linalg/lobpcg/lobpcg/fn.lobpcg.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../ndarray_linalg/lobpcg/fn.lobpcg.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/sidebar-items.js b/ndarray_linalg/lobpcg/sidebar-items.js new file mode 100644 index 00000000..e78c6ffd --- /dev/null +++ b/ndarray_linalg/lobpcg/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["LobpcgResult","The result of the eigensolver"],["TruncatedOrder","Find largest or smallest eigenvalues"]],"fn":[["lobpcg","Eigenvalue solver for large symmetric positive definite (SPD) eigenproblems"]],"struct":[["TruncatedEig","Truncated eigenproblem solver"],["TruncatedSvd","Truncated singular value decomposition"]]}; \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/struct.TruncatedEig.html b/ndarray_linalg/lobpcg/struct.TruncatedEig.html new file mode 100644 index 00000000..cb0dc7d0 --- /dev/null +++ b/ndarray_linalg/lobpcg/struct.TruncatedEig.html @@ -0,0 +1,48 @@ +TruncatedEig in ndarray_linalg::lobpcg - Rust + + + + + + +
pub struct TruncatedEig<A: Scalar> {
+    pub constraints: Option<Array2<A>>,
+    /* private fields */
+}
Expand description

Truncated eigenproblem solver

+

This struct wraps the LOBPCG algorithm and provides convenient builder-pattern access to +parameter like maximal iteration, precision and constraint matrix. Furthermore it allows +conversion into a iterative solver where each iteration step yields a new eigenvalue/vector +pair.

+

Fields

constraints: Option<Array2<A>>

Implementations

Trait Implementations

The type of the elements being iterated over.

+

Which kind of iterator are we turning this into?

+

Creates an iterator from a value. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/struct.TruncatedSvd.html b/ndarray_linalg/lobpcg/struct.TruncatedSvd.html new file mode 100644 index 00000000..88e24092 --- /dev/null +++ b/ndarray_linalg/lobpcg/struct.TruncatedSvd.html @@ -0,0 +1,40 @@ +TruncatedSvd in ndarray_linalg::lobpcg - Rust + + + + + + +
pub struct TruncatedSvd<A: Scalar> { /* private fields */ }
Expand description

Truncated singular value decomposition

+

Wraps the LOBPCG algorithm and provides convenient builder-pattern access to +parameter like maximal iteration, precision and constraint matrix.

+

Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/lobpcg/svd/struct.TruncatedSvd.html b/ndarray_linalg/lobpcg/svd/struct.TruncatedSvd.html new file mode 100644 index 00000000..720d000b --- /dev/null +++ b/ndarray_linalg/lobpcg/svd/struct.TruncatedSvd.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../ndarray_linalg/lobpcg/struct.TruncatedSvd.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_aclose!.html b/ndarray_linalg/macro.assert_aclose!.html new file mode 100644 index 00000000..fcfeb79a --- /dev/null +++ b/ndarray_linalg/macro.assert_aclose!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.assert_aclose.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_aclose.html b/ndarray_linalg/macro.assert_aclose.html new file mode 100644 index 00000000..789b7946 --- /dev/null +++ b/ndarray_linalg/macro.assert_aclose.html @@ -0,0 +1,30 @@ +assert_aclose in ndarray_linalg - Rust + + + + + + +
macro_rules! assert_aclose {
+    ($test: expr,$truth: expr,$tol: expr) => { ... };
+    ($test: expr,$truth: expr,$tol: expr; $comment: expr) => { ... };
+}
+
+ \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_close_l1!.html b/ndarray_linalg/macro.assert_close_l1!.html new file mode 100644 index 00000000..a95797cb --- /dev/null +++ b/ndarray_linalg/macro.assert_close_l1!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.assert_close_l1.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_close_l1.html b/ndarray_linalg/macro.assert_close_l1.html new file mode 100644 index 00000000..d5caff82 --- /dev/null +++ b/ndarray_linalg/macro.assert_close_l1.html @@ -0,0 +1,30 @@ +assert_close_l1 in ndarray_linalg - Rust + + + + + + +
macro_rules! assert_close_l1 {
+    ($test: expr,$truth: expr,$tol: expr) => { ... };
+    ($test: expr,$truth: expr,$tol: expr; $comment: expr) => { ... };
+}
+
+ \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_close_l2!.html b/ndarray_linalg/macro.assert_close_l2!.html new file mode 100644 index 00000000..c6b8024e --- /dev/null +++ b/ndarray_linalg/macro.assert_close_l2!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.assert_close_l2.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_close_l2.html b/ndarray_linalg/macro.assert_close_l2.html new file mode 100644 index 00000000..d1e02ef2 --- /dev/null +++ b/ndarray_linalg/macro.assert_close_l2.html @@ -0,0 +1,30 @@ +assert_close_l2 in ndarray_linalg - Rust + + + + + + +
macro_rules! assert_close_l2 {
+    ($test: expr,$truth: expr,$tol: expr) => { ... };
+    ($test: expr,$truth: expr,$tol: expr; $comment: expr) => { ... };
+}
+
+ \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_close_max!.html b/ndarray_linalg/macro.assert_close_max!.html new file mode 100644 index 00000000..8fd46f62 --- /dev/null +++ b/ndarray_linalg/macro.assert_close_max!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.assert_close_max.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_close_max.html b/ndarray_linalg/macro.assert_close_max.html new file mode 100644 index 00000000..9841b56b --- /dev/null +++ b/ndarray_linalg/macro.assert_close_max.html @@ -0,0 +1,30 @@ +assert_close_max in ndarray_linalg - Rust + + + + + + +
macro_rules! assert_close_max {
+    ($test: expr,$truth: expr,$tol: expr) => { ... };
+    ($test: expr,$truth: expr,$tol: expr; $comment: expr) => { ... };
+}
+
+ \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_rclose!.html b/ndarray_linalg/macro.assert_rclose!.html new file mode 100644 index 00000000..0c0391e6 --- /dev/null +++ b/ndarray_linalg/macro.assert_rclose!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.assert_rclose.html...

+ + + \ No newline at end of file diff --git a/ndarray_linalg/macro.assert_rclose.html b/ndarray_linalg/macro.assert_rclose.html new file mode 100644 index 00000000..3323e5aa --- /dev/null +++ b/ndarray_linalg/macro.assert_rclose.html @@ -0,0 +1,30 @@ +assert_rclose in ndarray_linalg - Rust + + + + + + +
macro_rules! assert_rclose {
+    ($test: expr,$truth: expr,$tol: expr) => { ... };
+    ($test: expr,$truth: expr,$tol: expr; $comment: expr) => { ... };
+}
+
+ \ No newline at end of file diff --git a/ndarray_linalg/norm/enum.NormalizeAxis.html b/ndarray_linalg/norm/enum.NormalizeAxis.html new file mode 100644 index 00000000..8f4e71ee --- /dev/null +++ b/ndarray_linalg/norm/enum.NormalizeAxis.html @@ -0,0 +1,40 @@ +NormalizeAxis in ndarray_linalg::norm - Rust + + + + + + +
pub enum NormalizeAxis {
+    Row,
+    Column,
+}

Variants

Row

Column

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/norm/fn.normalize.html b/ndarray_linalg/norm/fn.normalize.html new file mode 100644 index 00000000..69825b43 --- /dev/null +++ b/ndarray_linalg/norm/fn.normalize.html @@ -0,0 +1,27 @@ +normalize in ndarray_linalg::norm - Rust + + + + + + +
pub fn normalize<A, S>(
    m: ArrayBase<S, Ix2>,
    axis: NormalizeAxis
) -> (ArrayBase<S, Ix2>, Vec<A::Real>) where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>, 
Expand description

normalize in L2 norm

+
+ \ No newline at end of file diff --git a/ndarray_linalg/norm/index.html b/ndarray_linalg/norm/index.html new file mode 100644 index 00000000..f811a21d --- /dev/null +++ b/ndarray_linalg/norm/index.html @@ -0,0 +1,32 @@ +ndarray_linalg::norm - Rust + + + + + + +
Expand description

Norm of vectors

+

Enums

+

Traits

+

Define norm as a metric linear space (not as a matrix)

+

Functions

+

normalize in L2 norm

+
+ \ No newline at end of file diff --git a/ndarray_linalg/norm/sidebar-items.js b/ndarray_linalg/norm/sidebar-items.js new file mode 100644 index 00000000..ad2b2c21 --- /dev/null +++ b/ndarray_linalg/norm/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["NormalizeAxis",""]],"fn":[["normalize","normalize in L2 norm"]],"trait":[["Norm","Define norm as a metric linear space (not as a matrix)"]]}; \ No newline at end of file diff --git a/ndarray_linalg/norm/trait.Norm.html b/ndarray_linalg/norm/trait.Norm.html new file mode 100644 index 00000000..6949e948 --- /dev/null +++ b/ndarray_linalg/norm/trait.Norm.html @@ -0,0 +1,40 @@ +Norm in ndarray_linalg::norm - Rust + + + + + + +
pub trait Norm {
+    type Output;
+
+    fn norm_l1(&self) -> Self::Output;
+    fn norm_l2(&self) -> Self::Output;
+    fn norm_max(&self) -> Self::Output;
+
+    fn norm(&self) -> Self::Output { ... }
+}
Expand description

Define norm as a metric linear space (not as a matrix)

+

For operator norms, see opnorm module

+

Required Associated Types

Required Methods

L-1 norm

+

L-2 norm

+

maximum norm

+

Provided Methods

rename of norm_l2

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/operator/index.html b/ndarray_linalg/operator/index.html new file mode 100644 index 00000000..637e90d9 --- /dev/null +++ b/ndarray_linalg/operator/index.html @@ -0,0 +1,30 @@ +ndarray_linalg::operator - Rust + + + + + + +
Expand description

Linear operator algebra

+

Traits

+

Abstracted linear operator as an action to vector (ArrayBase<S, Ix1>) and matrix +(ArrayBase<S, Ix2)

+
+ \ No newline at end of file diff --git a/ndarray_linalg/operator/sidebar-items.js b/ndarray_linalg/operator/sidebar-items.js new file mode 100644 index 00000000..f0131421 --- /dev/null +++ b/ndarray_linalg/operator/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["LinearOperator","Abstracted linear operator as an action to vector (`ArrayBase`) and matrix (`ArrayBaseLinearOperator in ndarray_linalg::operator - Rust + + + + + + +
pub trait LinearOperator {
+    type Elem: Scalar;
+
+    fn apply<S>(&self, a: &ArrayBase<S, Ix1>) -> Array1<S::Elem>
    where
        S: Data<Elem = Self::Elem>
, + { ... } + fn apply_mut<S>(&self, a: &mut ArrayBase<S, Ix1>)
    where
        S: DataMut<Elem = Self::Elem>
, + { ... } + fn apply_into<S>(&self, a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix1>
    where
        S: DataOwned<Elem = Self::Elem> + DataMut
, + { ... } + fn apply2<S>(&self, a: &ArrayBase<S, Ix2>) -> Array2<S::Elem>
    where
        S: Data<Elem = Self::Elem>
, + { ... } + fn apply2_mut<S>(&self, a: &mut ArrayBase<S, Ix2>)
    where
        S: DataMut<Elem = Self::Elem>
, + { ... } + fn apply2_into<S>(&self, a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix2>
    where
        S: DataOwned<Elem = Self::Elem> + DataMut
, + { ... } +}
Expand description

Abstracted linear operator as an action to vector (ArrayBase<S, Ix1>) and matrix +(ArrayBase<S, Ix2)

+

Required Associated Types

Provided Methods

Apply operator out-place

+

Apply operator in-place

+

Apply operator with move

+

Apply operator to matrix out-place

+

Apply operator to matrix in-place

+

Apply operator to matrix with move

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/opnorm/enum.NormType.html b/ndarray_linalg/opnorm/enum.NormType.html new file mode 100644 index 00000000..9a204674 --- /dev/null +++ b/ndarray_linalg/opnorm/enum.NormType.html @@ -0,0 +1,49 @@ +NormType in ndarray_linalg::opnorm - Rust + + + + + + +
#[repr(u8)]
+pub enum NormType {
+    One,
+    Infinity,
+    Frobenius,
+}

Variants

One

Infinity

Frobenius

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/opnorm/index.html b/ndarray_linalg/opnorm/index.html new file mode 100644 index 00000000..4fdc2b88 --- /dev/null +++ b/ndarray_linalg/opnorm/index.html @@ -0,0 +1,30 @@ +ndarray_linalg::opnorm - Rust + + + + + + +
Expand description

Operator norm

+

Enums

+

Traits

+

Operator norm using *lange LAPACK routines

+
+ \ No newline at end of file diff --git a/ndarray_linalg/opnorm/sidebar-items.js b/ndarray_linalg/opnorm/sidebar-items.js new file mode 100644 index 00000000..5a362616 --- /dev/null +++ b/ndarray_linalg/opnorm/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["NormType",""]],"trait":[["OperationNorm","Operator norm using `*lange` LAPACK routines"]]}; \ No newline at end of file diff --git a/ndarray_linalg/opnorm/trait.OperationNorm.html b/ndarray_linalg/opnorm/trait.OperationNorm.html new file mode 100644 index 00000000..b8b54402 --- /dev/null +++ b/ndarray_linalg/opnorm/trait.OperationNorm.html @@ -0,0 +1,40 @@ +OperationNorm in ndarray_linalg::opnorm - Rust + + + + + + +
pub trait OperationNorm {
+    type Output: Scalar;
+
+    fn opnorm(&self, t: NormType) -> Result<Self::Output>;
+
+    fn opnorm_one(&self) -> Result<Self::Output> { ... }
+    fn opnorm_inf(&self) -> Result<Self::Output> { ... }
+    fn opnorm_fro(&self) -> Result<Self::Output> { ... }
+}
Expand description

Operator norm using *lange LAPACK routines

+

Wikipedia article on operator norm

+

Required Associated Types

the value of norm

+

Required Methods

Provided Methods

the one norm of a matrix (maximum column sum)

+

the infinity norm of a matrix (maximum row sum)

+

the Frobenius norm of a matrix (square root of sum of squares)

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/qr/enum.UPLO.html b/ndarray_linalg/qr/enum.UPLO.html new file mode 100644 index 00000000..d80ef17e --- /dev/null +++ b/ndarray_linalg/qr/enum.UPLO.html @@ -0,0 +1,49 @@ +UPLO in ndarray_linalg::qr - Rust + + + + + + +
#[repr(u8)]
+pub enum UPLO {
+    Upper,
+    Lower,
+}
Expand description

Upper/Lower specification for seveal usages

+

Variants

Upper

Lower

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/qr/index.html b/ndarray_linalg/qr/index.html new file mode 100644 index 00000000..c4e9e6d0 --- /dev/null +++ b/ndarray_linalg/qr/index.html @@ -0,0 +1,36 @@ +ndarray_linalg::qr - Rust + + + + + + +
Expand description

Enums

+

Upper/Lower specification for seveal usages

+

Traits

+

QR decomposition for matrix reference

+

QR decomposition

+

QR decomposition for square matrix reference

+

QR decomposition for mutable reference of square matrix

+

QR decomposition for square matrix

+
+ \ No newline at end of file diff --git a/ndarray_linalg/qr/sidebar-items.js b/ndarray_linalg/qr/sidebar-items.js new file mode 100644 index 00000000..1bf4250e --- /dev/null +++ b/ndarray_linalg/qr/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["UPLO","Upper/Lower specification for seveal usages"]],"trait":[["QR","QR decomposition for matrix reference"],["QRInto","QR decomposition"],["QRSquare","QR decomposition for square matrix reference"],["QRSquareInplace","QR decomposition for mutable reference of square matrix"],["QRSquareInto","QR decomposition for square matrix"]]}; \ No newline at end of file diff --git a/ndarray_linalg/qr/trait.QR.html b/ndarray_linalg/qr/trait.QR.html new file mode 100644 index 00000000..82fc80e6 --- /dev/null +++ b/ndarray_linalg/qr/trait.QR.html @@ -0,0 +1,34 @@ +QR in ndarray_linalg::qr - Rust + + + + + + +
pub trait QR {
+    type Q;
+    type R;
+
+    fn qr(&self) -> Result<(Self::Q, Self::R)>;
+}
Expand description

QR decomposition for matrix reference

+

This creates copy due for reshaping array. +To avoid copy and the matrix is square, please use QRSquare* traits.

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/qr/trait.QRInto.html b/ndarray_linalg/qr/trait.QRInto.html new file mode 100644 index 00000000..0408e748 --- /dev/null +++ b/ndarray_linalg/qr/trait.QRInto.html @@ -0,0 +1,34 @@ +QRInto in ndarray_linalg::qr - Rust + + + + + + +
pub trait QRInto: Sized {
+    type Q;
+    type R;
+
+    fn qr_into(self) -> Result<(Self::Q, Self::R)>;
+}
Expand description

QR decomposition

+

This creates copy due for reshaping array. +To avoid copy and the matrix is square, please use QRSquare* traits.

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/qr/trait.QRSquare.html b/ndarray_linalg/qr/trait.QRSquare.html new file mode 100644 index 00000000..b9029756 --- /dev/null +++ b/ndarray_linalg/qr/trait.QRSquare.html @@ -0,0 +1,32 @@ +QRSquare in ndarray_linalg::qr - Rust + + + + + + +
pub trait QRSquare: Sized {
+    type Q;
+    type R;
+
+    fn qr_square(&self) -> Result<(Self::Q, Self::R)>;
+}
Expand description

QR decomposition for square matrix reference

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/qr/trait.QRSquareInplace.html b/ndarray_linalg/qr/trait.QRSquareInplace.html new file mode 100644 index 00000000..1c57c88c --- /dev/null +++ b/ndarray_linalg/qr/trait.QRSquareInplace.html @@ -0,0 +1,31 @@ +QRSquareInplace in ndarray_linalg::qr - Rust + + + + + + +
pub trait QRSquareInplace: Sized {
+    type R;
+
+    fn qr_square_inplace(&mut self) -> Result<(&mut Self, Self::R)>;
+}
Expand description

QR decomposition for mutable reference of square matrix

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/qr/trait.QRSquareInto.html b/ndarray_linalg/qr/trait.QRSquareInto.html new file mode 100644 index 00000000..7d175ebf --- /dev/null +++ b/ndarray_linalg/qr/trait.QRSquareInto.html @@ -0,0 +1,31 @@ +QRSquareInto in ndarray_linalg::qr - Rust + + + + + + +
pub trait QRSquareInto: Sized {
+    type R;
+
+    fn qr_square_into(self) -> Result<(Self, Self::R)>;
+}
Expand description

QR decomposition for square matrix

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/sidebar-items.js b/ndarray_linalg/sidebar-items.js new file mode 100644 index 00000000..0bf58e8b --- /dev/null +++ b/ndarray_linalg/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["TruncatedOrder","Find largest or smallest eigenvalues"]],"macro":[["assert_aclose",""],["assert_close_l1",""],["assert_close_l2",""],["assert_close_max",""],["assert_rclose",""]],"mod":[["assert","Assertions for array"],["cholesky","Cholesky decomposition of Hermitian (or real symmetric) positive definite matrices"],["convert","utilities for convert array"],["diagonal","Vector as a Diagonal matrix"],["eig","Eigenvalue decomposition for non-symmetric square matrices"],["eigh","Eigendecomposition for Hermitian matrices."],["error","Define Errors"],["generate","Generator functions for matrices"],["inner",""],["krylov","Krylov subspace methods"],["layout","Convert ndarray into LAPACK-compatible matrix format"],["least_squares","Least Squares"],["lobpcg",""],["norm","Norm of vectors"],["operator","Linear operator algebra"],["opnorm","Operator norm"],["qr","QR decomposition"],["solve","Solve systems of linear equations and invert matrices"],["solveh","Solve Hermitian (or real symmetric) linear problems and invert Hermitian (or real symmetric) matrices"],["svd","Singular-value decomposition (SVD)"],["svddc","Singular-value decomposition (SVD) by divide-and-conquer (?gesdd)"],["trace","Trace calculation"],["triangular","Methods for triangular matrices"],["tridiagonal","Vectors as a Tridiagonal matrix & Methods for tridiagonal matrices"],["types","Basic types and their methods for linear algebra"]],"struct":[["TruncatedEig","Truncated eigenproblem solver"],["TruncatedSvd","Truncated singular value decomposition"]]}; \ No newline at end of file diff --git a/ndarray_linalg/solve/enum.Transpose.html b/ndarray_linalg/solve/enum.Transpose.html new file mode 100644 index 00000000..8ea42af8 --- /dev/null +++ b/ndarray_linalg/solve/enum.Transpose.html @@ -0,0 +1,49 @@ +Transpose in ndarray_linalg::solve - Rust + + + + + + +
#[repr(u8)]
+pub enum Transpose {
+    No,
+    Transpose,
+    Hermite,
+}

Variants

No

Transpose

Hermite

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/solve/index.html b/ndarray_linalg/solve/index.html new file mode 100644 index 00000000..4ab766cb --- /dev/null +++ b/ndarray_linalg/solve/index.html @@ -0,0 +1,73 @@ +ndarray_linalg::solve - Rust + + + + + + +
Expand description

Solve systems of linear equations and invert matrices

+

Examples

+

Solve A * x = b:

+ +
#[macro_use]
+extern crate ndarray;
+extern crate ndarray_linalg;
+
+use ndarray::prelude::*;
+use ndarray_linalg::Solve;
+
+let a: Array2<f64> = array![[3., 2., -1.], [2., -2., 4.], [-2., 1., -2.]];
+let b: Array1<f64> = array![1., -2., 0.];
+let x = a.solve_into(b).unwrap();
+assert!(x.abs_diff_eq(&array![1., -2., -2.], 1e-9));
+
+

There are also special functions for solving A^T * x = b and +A^H * x = b.

+

If you are solving multiple systems of linear equations with the same +coefficient matrix A, it’s faster to compute the LU factorization once at +the beginning than solving directly using A:

+ +

+use ndarray::prelude::*;
+use ndarray_linalg::*;
+
+let a: Array2<f64> = random((3, 3));
+let f = a.factorize_into().unwrap(); // LU factorize A (A is consumed)
+for _ in 0..10 {
+    let b: Array1<f64> = random(3);
+    let x = f.solve_into(b).unwrap(); // Solve A * x = b using factorized L, U
+}
+
+

Structs

+

Represents the LU factorization of a matrix A as A = P*L*U.

+

Enums

+

Traits

+

An interface for calculating determinants of matrix refs.

+

An interface for calculating determinants of matrices.

+

An interface for computing LU factorizations of matrix refs.

+

An interface for computing LU factorizations of matrices.

+

An interface for inverting matrix refs.

+

An interface for inverting matrices.

+

An interface for estimating the reciprocal condition number of matrix refs.

+

An interface for estimating the reciprocal condition number of matrices.

+

An interface for solving systems of linear equations.

+

Type Definitions

+
+ \ No newline at end of file diff --git a/ndarray_linalg/solve/sidebar-items.js b/ndarray_linalg/solve/sidebar-items.js new file mode 100644 index 00000000..d1344c7f --- /dev/null +++ b/ndarray_linalg/solve/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["Transpose",""]],"struct":[["LUFactorized","Represents the LU factorization of a matrix `A` as `A = P*L*U`."]],"trait":[["Determinant","An interface for calculating determinants of matrix refs."],["DeterminantInto","An interface for calculating determinants of matrices."],["Factorize","An interface for computing LU factorizations of matrix refs."],["FactorizeInto","An interface for computing LU factorizations of matrices."],["Inverse","An interface for inverting matrix refs."],["InverseInto","An interface for inverting matrices."],["ReciprocalConditionNum","An interface for estimating the reciprocal condition number of matrix refs."],["ReciprocalConditionNumInto","An interface for estimating the reciprocal condition number of matrices."],["Solve","An interface for solving systems of linear equations."]],"type":[["Pivot",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/solve/struct.LUFactorized.html b/ndarray_linalg/solve/struct.LUFactorized.html new file mode 100644 index 00000000..412b60c8 --- /dev/null +++ b/ndarray_linalg/solve/struct.LUFactorized.html @@ -0,0 +1,71 @@ +LUFactorized in ndarray_linalg::solve - Rust + + + + + + +
pub struct LUFactorized<S: Data + RawDataClone> { /* private fields */ }
Expand description

Represents the LU factorization of a matrix A as A = P*L*U.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Computes the (sign, natural_log) of the determinant of the matrix. Read more

+

Computes the determinant of the matrix.

+

Computes the (sign, natural_log) of the determinant of the matrix. Read more

+

Computes the determinant of the matrix.

+

Computes the inverse of the matrix.

+

Computes the inverse of the matrix.

+

Estimates the reciprocal of the condition number of the matrix in +1-norm. Read more

+

Estimates the reciprocal of the condition number of the matrix in +1-norm. Read more

+

Solves a system of linear equations A * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Solves a system of linear equations A * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Solves a system of linear equations A * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b where A is self, b +is the argument, and x is the successful result. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.Determinant.html b/ndarray_linalg/solve/trait.Determinant.html new file mode 100644 index 00000000..79f4300f --- /dev/null +++ b/ndarray_linalg/solve/trait.Determinant.html @@ -0,0 +1,43 @@ +Determinant in ndarray_linalg::solve - Rust + + + + + + +
pub trait Determinant<A: Scalar> {
+    fn sln_det(&self) -> Result<(A, A::Real)>;
+
+    fn det(&self) -> Result<A> { ... }
+}
Expand description

An interface for calculating determinants of matrix refs.

+

Required Methods

Computes the (sign, natural_log) of the determinant of the matrix.

+

For real matrices, sign is 1, 0, or -1. For complex matrices, +sign is 0 or a complex number with absolute value 1. The +natural_log is the natural logarithm of the absolute value of the +determinant. If the determinant is zero, sign is 0 and natural_log +is negative infinity.

+

To obtain the determinant, you can compute sign * natural_log.exp() +or just call .det() instead.

+

This method is more robust than .det() to very small or very large +determinants since it returns the natural logarithm of the determinant +rather than the determinant itself.

+

Provided Methods

Computes the determinant of the matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.DeterminantInto.html b/ndarray_linalg/solve/trait.DeterminantInto.html new file mode 100644 index 00000000..0775ee43 --- /dev/null +++ b/ndarray_linalg/solve/trait.DeterminantInto.html @@ -0,0 +1,43 @@ +DeterminantInto in ndarray_linalg::solve - Rust + + + + + + +
pub trait DeterminantInto<A: Scalar>: Sized {
+    fn sln_det_into(self) -> Result<(A, A::Real)>;
+
+    fn det_into(self) -> Result<A> { ... }
+}
Expand description

An interface for calculating determinants of matrices.

+

Required Methods

Computes the (sign, natural_log) of the determinant of the matrix.

+

For real matrices, sign is 1, 0, or -1. For complex matrices, +sign is 0 or a complex number with absolute value 1. The +natural_log is the natural logarithm of the absolute value of the +determinant. If the determinant is zero, sign is 0 and natural_log +is negative infinity.

+

To obtain the determinant, you can compute sign * natural_log.exp() +or just call .det_into() instead.

+

This method is more robust than .det() to very small or very large +determinants since it returns the natural logarithm of the determinant +rather than the determinant itself.

+

Provided Methods

Computes the determinant of the matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.Factorize.html b/ndarray_linalg/solve/trait.Factorize.html new file mode 100644 index 00000000..7fb5f621 --- /dev/null +++ b/ndarray_linalg/solve/trait.Factorize.html @@ -0,0 +1,31 @@ +Factorize in ndarray_linalg::solve - Rust + + + + + + +
pub trait Factorize<S: Data + RawDataClone> {
+    fn factorize(&self) -> Result<LUFactorized<S>>;
+}
Expand description

An interface for computing LU factorizations of matrix refs.

+

Required Methods

Computes the LU factorization A = P*L*U, where P is a permutation +matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.FactorizeInto.html b/ndarray_linalg/solve/trait.FactorizeInto.html new file mode 100644 index 00000000..75db76f8 --- /dev/null +++ b/ndarray_linalg/solve/trait.FactorizeInto.html @@ -0,0 +1,31 @@ +FactorizeInto in ndarray_linalg::solve - Rust + + + + + + +
pub trait FactorizeInto<S: Data + RawDataClone> {
+    fn factorize_into(self) -> Result<LUFactorized<S>>;
+}
Expand description

An interface for computing LU factorizations of matrices.

+

Required Methods

Computes the LU factorization A = P*L*U, where P is a permutation +matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.Inverse.html b/ndarray_linalg/solve/trait.Inverse.html new file mode 100644 index 00000000..401048f7 --- /dev/null +++ b/ndarray_linalg/solve/trait.Inverse.html @@ -0,0 +1,32 @@ +Inverse in ndarray_linalg::solve - Rust + + + + + + +
pub trait Inverse {
+    type Output;
+
+    fn inv(&self) -> Result<Self::Output>;
+}
Expand description

An interface for inverting matrix refs.

+

Required Associated Types

Required Methods

Computes the inverse of the matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.InverseInto.html b/ndarray_linalg/solve/trait.InverseInto.html new file mode 100644 index 00000000..bd007b61 --- /dev/null +++ b/ndarray_linalg/solve/trait.InverseInto.html @@ -0,0 +1,32 @@ +InverseInto in ndarray_linalg::solve - Rust + + + + + + +
pub trait InverseInto {
+    type Output;
+
+    fn inv_into(self) -> Result<Self::Output>;
+}
Expand description

An interface for inverting matrices.

+

Required Associated Types

Required Methods

Computes the inverse of the matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.ReciprocalConditionNum.html b/ndarray_linalg/solve/trait.ReciprocalConditionNum.html new file mode 100644 index 00000000..c7e324fd --- /dev/null +++ b/ndarray_linalg/solve/trait.ReciprocalConditionNum.html @@ -0,0 +1,37 @@ +ReciprocalConditionNum in ndarray_linalg::solve - Rust + + + + + + +
pub trait ReciprocalConditionNum<A: Scalar> {
+    fn rcond(&self) -> Result<A::Real>;
+}
Expand description

An interface for estimating the reciprocal condition number of matrix refs.

+

Required Methods

Estimates the reciprocal of the condition number of the matrix in +1-norm.

+

This method uses the LAPACK *gecon routines, which estimate +self.inv().opnorm_one() and then compute rcond = 1. / (self.opnorm_one() * self.inv().opnorm_one()).

+
    +
  • If rcond is near 0., the matrix is badly conditioned.
  • +
  • If rcond is near 1., the matrix is well conditioned.
  • +
+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.ReciprocalConditionNumInto.html b/ndarray_linalg/solve/trait.ReciprocalConditionNumInto.html new file mode 100644 index 00000000..f698aeae --- /dev/null +++ b/ndarray_linalg/solve/trait.ReciprocalConditionNumInto.html @@ -0,0 +1,37 @@ +ReciprocalConditionNumInto in ndarray_linalg::solve - Rust + + + + + + +
pub trait ReciprocalConditionNumInto<A: Scalar> {
+    fn rcond_into(self) -> Result<A::Real>;
+}
Expand description

An interface for estimating the reciprocal condition number of matrices.

+

Required Methods

Estimates the reciprocal of the condition number of the matrix in +1-norm.

+

This method uses the LAPACK *gecon routines, which estimate +self.inv().opnorm_one() and then compute rcond = 1. / (self.opnorm_one() * self.inv().opnorm_one()).

+
    +
  • If rcond is near 0., the matrix is badly conditioned.
  • +
  • If rcond is near 1., the matrix is well conditioned.
  • +
+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/trait.Solve.html b/ndarray_linalg/solve/trait.Solve.html new file mode 100644 index 00000000..dbe57bc3 --- /dev/null +++ b/ndarray_linalg/solve/trait.Solve.html @@ -0,0 +1,98 @@ +Solve in ndarray_linalg::solve - Rust + + + + + + +
pub trait Solve<A: Scalar> {
+    fn solve_inplace<'a, S: DataMut<Elem = A>>(
        &self,
        b: &'a mut ArrayBase<S, Ix1>
    ) -> Result<&'a mut ArrayBase<S, Ix1>>; + fn solve_t_inplace<'a, S: DataMut<Elem = A>>(
        &self,
        b: &'a mut ArrayBase<S, Ix1>
    ) -> Result<&'a mut ArrayBase<S, Ix1>>; + fn solve_h_inplace<'a, S: DataMut<Elem = A>>(
        &self,
        b: &'a mut ArrayBase<S, Ix1>
    ) -> Result<&'a mut ArrayBase<S, Ix1>>; + + fn solve<S: Data<Elem = A>>(
        &self,
        b: &ArrayBase<S, Ix1>
    ) -> Result<Array1<A>> { ... } + fn solve_into<S: DataMut<Elem = A>>(
        &self,
        b: ArrayBase<S, Ix1>
    ) -> Result<ArrayBase<S, Ix1>> { ... } + fn solve_t<S: Data<Elem = A>>(
        &self,
        b: &ArrayBase<S, Ix1>
    ) -> Result<Array1<A>> { ... } + fn solve_t_into<S: DataMut<Elem = A>>(
        &self,
        b: ArrayBase<S, Ix1>
    ) -> Result<ArrayBase<S, Ix1>> { ... } + fn solve_h<S: Data<Elem = A>>(
        &self,
        b: &ArrayBase<S, Ix1>
    ) -> Result<Array1<A>> { ... } + fn solve_h_into<S: DataMut<Elem = A>>(
        &self,
        b: ArrayBase<S, Ix1>
    ) -> Result<ArrayBase<S, Ix1>> { ... } +}
Expand description

An interface for solving systems of linear equations.

+

There are three groups of methods:

+
    +
  • solve* (normal) methods solve A * x = b for x.
  • +
  • solve_t* (transpose) methods solve A^T * x = b for x.
  • +
  • solve_h* (Hermitian conjugate) methods solve A^H * x = b for x.
  • +
+

Within each group, there are three methods that handle ownership differently:

+
    +
  • * methods take a reference to b and return x as a new array.
  • +
  • *_into methods take ownership of b, store the result in it, and return it.
  • +
  • *_inplace methods take a mutable reference to b and store the result in that array.
  • +
+

If you plan to solve many equations with the same A matrix but different +b vectors, it’s faster to factor the A matrix once using the +Factorize trait, and then solve using the LUFactorized struct.

+

Required Methods

Solves a system of linear equations A * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of columns +of A.

+

Solves a system of linear equations A^T * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of rows of +A.

+

Solves a system of linear equations A^H * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of rows of +A.

+

Provided Methods

Solves a system of linear equations A * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of columns +of A.

+

Solves a system of linear equations A * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of columns +of A.

+

Solves a system of linear equations A^T * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of rows of +A.

+

Solves a system of linear equations A^T * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of rows of +A.

+

Solves a system of linear equations A^H * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of rows of +A.

+

Solves a system of linear equations A^H * x = b where A is self, b +is the argument, and x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of rows of +A.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solve/type.Pivot.html b/ndarray_linalg/solve/type.Pivot.html new file mode 100644 index 00000000..300d6c40 --- /dev/null +++ b/ndarray_linalg/solve/type.Pivot.html @@ -0,0 +1,26 @@ +Pivot in ndarray_linalg::solve - Rust + + + + + + +
+

Type Definition ndarray_linalg::solve::Pivot

[]
pub type Pivot = Vec<i32, Global>;
+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/enum.UPLO.html b/ndarray_linalg/solveh/enum.UPLO.html new file mode 100644 index 00000000..2afaeddf --- /dev/null +++ b/ndarray_linalg/solveh/enum.UPLO.html @@ -0,0 +1,49 @@ +UPLO in ndarray_linalg::solveh - Rust + + + + + + +
#[repr(u8)]
+pub enum UPLO {
+    Upper,
+    Lower,
+}
Expand description

Upper/Lower specification for seveal usages

+

Variants

Upper

Lower

Implementations

To use Fortran LAPACK API in lapack-sys crate

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/index.html b/ndarray_linalg/solveh/index.html new file mode 100644 index 00000000..1e33bfa9 --- /dev/null +++ b/ndarray_linalg/solveh/index.html @@ -0,0 +1,78 @@ +ndarray_linalg::solveh - Rust + + + + + + +
Expand description

Solve Hermitian (or real symmetric) linear problems and invert Hermitian +(or real symmetric) matrices

+

Note that only the upper triangular portion of the matrix is used.

+

Examples

+

Solve A * x = b, where A is a Hermitian (or real symmetric) matrix:

+ +
#[macro_use]
+extern crate ndarray;
+extern crate ndarray_linalg;
+
+use ndarray::prelude::*;
+use ndarray_linalg::SolveH;
+
+let a: Array2<f64> = array![
+    [3., 2., -1.],
+    [2., -2., 4.],
+    [-1., 4., 5.]
+];
+let b: Array1<f64> = array![11., -12., 1.];
+let x = a.solveh_into(b).unwrap();
+assert!(x.abs_diff_eq(&array![1., 3., -2.], 1e-9));
+
+

If you are solving multiple systems of linear equations with the same +Hermitian or real symmetric coefficient matrix A, it’s faster to compute +the factorization once at the beginning than solving directly using A:

+ +
use ndarray::prelude::*;
+use ndarray_linalg::*;
+
+let a: Array2<f64> = random((3, 3));
+let f = a.factorizeh_into().unwrap(); // Factorize A (A is consumed)
+for _ in 0..10 {
+    let b: Array1<f64> = random(3);
+    let x = f.solveh_into(b).unwrap(); // Solve A * x = b using the factorization
+}
+
+

Structs

+

Represents the Bunch–Kaufman factorization of a Hermitian (or real +symmetric) matrix as A = P * U * D * U^H * P^T.

+

Enums

+

Upper/Lower specification for seveal usages

+

Traits

+

An interface for calculating determinants of Hermitian (or real symmetric) matrix refs.

+

An interface for calculating determinants of Hermitian (or real symmetric) matrices.

+

An interface for computing the Bunch–Kaufman factorization of Hermitian (or +real symmetric) matrix refs.

+

An interface for computing the Bunch–Kaufman factorization of Hermitian (or +real symmetric) matrices.

+

An interface for inverting Hermitian (or real symmetric) matrix refs.

+

An interface for inverting Hermitian (or real symmetric) matrices.

+

An interface for solving systems of Hermitian (or real symmetric) linear equations.

+

Type Definitions

+
+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/sidebar-items.js b/ndarray_linalg/solveh/sidebar-items.js new file mode 100644 index 00000000..1fbde7a4 --- /dev/null +++ b/ndarray_linalg/solveh/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["UPLO","Upper/Lower specification for seveal usages"]],"struct":[["BKFactorized","Represents the Bunch–Kaufman factorization of a Hermitian (or real symmetric) matrix as `A = P * U * D * U^H * P^T`."]],"trait":[["DeterminantH","An interface for calculating determinants of Hermitian (or real symmetric) matrix refs."],["DeterminantHInto","An interface for calculating determinants of Hermitian (or real symmetric) matrices."],["FactorizeH","An interface for computing the Bunch–Kaufman factorization of Hermitian (or real symmetric) matrix refs."],["FactorizeHInto","An interface for computing the Bunch–Kaufman factorization of Hermitian (or real symmetric) matrices."],["InverseH","An interface for inverting Hermitian (or real symmetric) matrix refs."],["InverseHInto","An interface for inverting Hermitian (or real symmetric) matrices."],["SolveH","An interface for solving systems of Hermitian (or real symmetric) linear equations."]],"type":[["Pivot",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/solveh/struct.BKFactorized.html b/ndarray_linalg/solveh/struct.BKFactorized.html new file mode 100644 index 00000000..3d14056d --- /dev/null +++ b/ndarray_linalg/solveh/struct.BKFactorized.html @@ -0,0 +1,78 @@ +BKFactorized in ndarray_linalg::solveh - Rust + + + + + + +
pub struct BKFactorized<S: Data> {
+    pub a: ArrayBase<S, Ix2>,
+    pub ipiv: Pivot,
+}
Expand description

Represents the Bunch–Kaufman factorization of a Hermitian (or real +symmetric) matrix as A = P * U * D * U^H * P^T.

+

Fields

a: ArrayBase<S, Ix2>ipiv: Pivot

Implementations

Computes the determinant of the factorized Hermitian (or real +symmetric) matrix.

+

Computes the (sign, natural_log) of the determinant of the factorized +Hermitian (or real symmetric) matrix.

+

The natural_log is the natural logarithm of the absolute value of the +determinant. If the determinant is zero, sign is 0 and natural_log +is negative infinity.

+

To obtain the determinant, you can compute sign * natural_log.exp() +or just call .deth() instead.

+

This method is more robust than .deth() to very small or very large +determinants since it returns the natural logarithm of the determinant +rather than the determinant itself.

+

Computes the determinant of the factorized Hermitian (or real +symmetric) matrix.

+

Computes the (sign, natural_log) of the determinant of the factorized +Hermitian (or real symmetric) matrix.

+

The natural_log is the natural logarithm of the absolute value of the +determinant. If the determinant is zero, sign is 0 and natural_log +is negative infinity.

+

To obtain the determinant, you can compute sign * natural_log.exp() +or just call .deth_into() instead.

+

This method is more robust than .deth_into() to very small or very +large determinants since it returns the natural logarithm of the +determinant rather than the determinant itself.

+

Trait Implementations

Computes the inverse of the Hermitian (or real symmetric) matrix.

+

Computes the inverse of the Hermitian (or real symmetric) matrix.

+

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument. Read more

+

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/trait.DeterminantH.html b/ndarray_linalg/solveh/trait.DeterminantH.html new file mode 100644 index 00000000..abd4abfc --- /dev/null +++ b/ndarray_linalg/solveh/trait.DeterminantH.html @@ -0,0 +1,44 @@ +DeterminantH in ndarray_linalg::solveh - Rust + + + + + + +
pub trait DeterminantH {
+    type Elem: Scalar;
+
+    fn deth(&self) -> Result<<Self::Elem as Scalar>::Real>;
+    fn sln_deth(
        &self
    ) -> Result<(<Self::Elem as Scalar>::Real, <Self::Elem as Scalar>::Real)>; +}
Expand description

An interface for calculating determinants of Hermitian (or real symmetric) matrix refs.

+

Required Associated Types

The element type of the matrix.

+

Required Methods

Computes the determinant of the Hermitian (or real symmetric) matrix.

+

Computes the (sign, natural_log) of the determinant of the Hermitian +(or real symmetric) matrix.

+

The natural_log is the natural logarithm of the absolute value of the +determinant. If the determinant is zero, sign is 0 and natural_log +is negative infinity.

+

To obtain the determinant, you can compute sign * natural_log.exp() +or just call .deth() instead.

+

This method is more robust than .deth() to very small or very large +determinants since it returns the natural logarithm of the determinant +rather than the determinant itself.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/trait.DeterminantHInto.html b/ndarray_linalg/solveh/trait.DeterminantHInto.html new file mode 100644 index 00000000..669ebc10 --- /dev/null +++ b/ndarray_linalg/solveh/trait.DeterminantHInto.html @@ -0,0 +1,44 @@ +DeterminantHInto in ndarray_linalg::solveh - Rust + + + + + + +
pub trait DeterminantHInto {
+    type Elem: Scalar;
+
+    fn deth_into(self) -> Result<<Self::Elem as Scalar>::Real>;
+    fn sln_deth_into(
        self
    ) -> Result<(<Self::Elem as Scalar>::Real, <Self::Elem as Scalar>::Real)>; +}
Expand description

An interface for calculating determinants of Hermitian (or real symmetric) matrices.

+

Required Associated Types

The element type of the matrix.

+

Required Methods

Computes the determinant of the Hermitian (or real symmetric) matrix.

+

Computes the (sign, natural_log) of the determinant of the Hermitian +(or real symmetric) matrix.

+

The natural_log is the natural logarithm of the absolute value of the +determinant. If the determinant is zero, sign is 0 and natural_log +is negative infinity.

+

To obtain the determinant, you can compute sign * natural_log.exp() +or just call .deth_into() instead.

+

This method is more robust than .deth_into() to very small or very +large determinants since it returns the natural logarithm of the +determinant rather than the determinant itself.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/trait.FactorizeH.html b/ndarray_linalg/solveh/trait.FactorizeH.html new file mode 100644 index 00000000..f19df16e --- /dev/null +++ b/ndarray_linalg/solveh/trait.FactorizeH.html @@ -0,0 +1,32 @@ +FactorizeH in ndarray_linalg::solveh - Rust + + + + + + +
pub trait FactorizeH<S: Data> {
+    fn factorizeh(&self) -> Result<BKFactorized<S>>;
+}
Expand description

An interface for computing the Bunch–Kaufman factorization of Hermitian (or +real symmetric) matrix refs.

+

Required Methods

Computes the Bunch–Kaufman factorization of a Hermitian (or real +symmetric) matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/trait.FactorizeHInto.html b/ndarray_linalg/solveh/trait.FactorizeHInto.html new file mode 100644 index 00000000..e02cc0a5 --- /dev/null +++ b/ndarray_linalg/solveh/trait.FactorizeHInto.html @@ -0,0 +1,32 @@ +FactorizeHInto in ndarray_linalg::solveh - Rust + + + + + + +
pub trait FactorizeHInto<S: Data> {
+    fn factorizeh_into(self) -> Result<BKFactorized<S>>;
+}
Expand description

An interface for computing the Bunch–Kaufman factorization of Hermitian (or +real symmetric) matrices.

+

Required Methods

Computes the Bunch–Kaufman factorization of a Hermitian (or real +symmetric) matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/trait.InverseH.html b/ndarray_linalg/solveh/trait.InverseH.html new file mode 100644 index 00000000..25133206 --- /dev/null +++ b/ndarray_linalg/solveh/trait.InverseH.html @@ -0,0 +1,32 @@ +InverseH in ndarray_linalg::solveh - Rust + + + + + + +
pub trait InverseH {
+    type Output;
+
+    fn invh(&self) -> Result<Self::Output>;
+}
Expand description

An interface for inverting Hermitian (or real symmetric) matrix refs.

+

Required Associated Types

Required Methods

Computes the inverse of the Hermitian (or real symmetric) matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/trait.InverseHInto.html b/ndarray_linalg/solveh/trait.InverseHInto.html new file mode 100644 index 00000000..29740de6 --- /dev/null +++ b/ndarray_linalg/solveh/trait.InverseHInto.html @@ -0,0 +1,32 @@ +InverseHInto in ndarray_linalg::solveh - Rust + + + + + + +
pub trait InverseHInto {
+    type Output;
+
+    fn invh_into(self) -> Result<Self::Output>;
+}
Expand description

An interface for inverting Hermitian (or real symmetric) matrices.

+

Required Associated Types

Required Methods

Computes the inverse of the Hermitian (or real symmetric) matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/trait.SolveH.html b/ndarray_linalg/solveh/trait.SolveH.html new file mode 100644 index 00000000..1f1d49c7 --- /dev/null +++ b/ndarray_linalg/solveh/trait.SolveH.html @@ -0,0 +1,55 @@ +SolveH in ndarray_linalg::solveh - Rust + + + + + + +
pub trait SolveH<A: Scalar> {
+    fn solveh_inplace<'a, S: DataMut<Elem = A>>(
        &self,
        b: &'a mut ArrayBase<S, Ix1>
    ) -> Result<&'a mut ArrayBase<S, Ix1>>; + + fn solveh<S: Data<Elem = A>>(
        &self,
        b: &ArrayBase<S, Ix1>
    ) -> Result<Array1<A>> { ... } + fn solveh_into<S: DataMut<Elem = A>>(
        &self,
        b: ArrayBase<S, Ix1>
    ) -> Result<ArrayBase<S, Ix1>> { ... } +}
Expand description

An interface for solving systems of Hermitian (or real symmetric) linear equations.

+

If you plan to solve many equations with the same Hermitian (or real +symmetric) coefficient matrix A but different b vectors, it’s faster to +factor the A matrix once using the FactorizeH trait, and then solve +using the BKFactorized struct.

+

Required Methods

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument.

+
Panics
+

Panics if the length of b is not the equal to the number of columns +of A.

+

Provided Methods

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) matrix A, where A is self, b is the argument, and +x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of columns +of A.

+

Solves a system of linear equations A * x = b with Hermitian (or real +symmetric) matrix A, where A is self, b is the argument, and +x is the successful result.

+
Panics
+

Panics if the length of b is not the equal to the number of columns +of A.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/solveh/type.Pivot.html b/ndarray_linalg/solveh/type.Pivot.html new file mode 100644 index 00000000..a051d89e --- /dev/null +++ b/ndarray_linalg/solveh/type.Pivot.html @@ -0,0 +1,26 @@ +Pivot in ndarray_linalg::solveh - Rust + + + + + + +
+

Type Definition ndarray_linalg::solveh::Pivot

[]
pub type Pivot = Vec<i32, Global>;
+ \ No newline at end of file diff --git a/ndarray_linalg/struct.TruncatedEig.html b/ndarray_linalg/struct.TruncatedEig.html new file mode 100644 index 00000000..2e8da9ee --- /dev/null +++ b/ndarray_linalg/struct.TruncatedEig.html @@ -0,0 +1,48 @@ +TruncatedEig in ndarray_linalg - Rust + + + + + + +
pub struct TruncatedEig<A: Scalar> {
+    pub constraints: Option<Array2<A>>,
+    /* private fields */
+}
Expand description

Truncated eigenproblem solver

+

This struct wraps the LOBPCG algorithm and provides convenient builder-pattern access to +parameter like maximal iteration, precision and constraint matrix. Furthermore it allows +conversion into a iterative solver where each iteration step yields a new eigenvalue/vector +pair.

+

Fields

constraints: Option<Array2<A>>

Implementations

Trait Implementations

The type of the elements being iterated over.

+

Which kind of iterator are we turning this into?

+

Creates an iterator from a value. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/struct.TruncatedSvd.html b/ndarray_linalg/struct.TruncatedSvd.html new file mode 100644 index 00000000..c7a41b39 --- /dev/null +++ b/ndarray_linalg/struct.TruncatedSvd.html @@ -0,0 +1,40 @@ +TruncatedSvd in ndarray_linalg - Rust + + + + + + +
pub struct TruncatedSvd<A: Scalar> { /* private fields */ }
Expand description

Truncated singular value decomposition

+

Wraps the LOBPCG algorithm and provides convenient builder-pattern access to +parameter like maximal iteration, precision and constraint matrix.

+

Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/svd/index.html b/ndarray_linalg/svd/index.html new file mode 100644 index 00000000..10b793e2 --- /dev/null +++ b/ndarray_linalg/svd/index.html @@ -0,0 +1,32 @@ +ndarray_linalg::svd - Rust + + + + + + +
Expand description

Singular-value decomposition (SVD)

+

Wikipedia article on SVD

+

Traits

+

singular-value decomposition of matrix reference

+

singular-value decomposition for mutable reference of matrix

+

singular-value decomposition

+
+ \ No newline at end of file diff --git a/ndarray_linalg/svd/sidebar-items.js b/ndarray_linalg/svd/sidebar-items.js new file mode 100644 index 00000000..5f591bda --- /dev/null +++ b/ndarray_linalg/svd/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["SVD","singular-value decomposition of matrix reference"],["SVDInplace","singular-value decomposition for mutable reference of matrix"],["SVDInto","singular-value decomposition"]]}; \ No newline at end of file diff --git a/ndarray_linalg/svd/trait.SVD.html b/ndarray_linalg/svd/trait.SVD.html new file mode 100644 index 00000000..b8f50ce1 --- /dev/null +++ b/ndarray_linalg/svd/trait.SVD.html @@ -0,0 +1,33 @@ +SVD in ndarray_linalg::svd - Rust + + + + + + +
pub trait SVD {
+    type U;
+    type VT;
+    type Sigma;
+
+    fn svd(
        &self,
        calc_u: bool,
        calc_vt: bool
    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>; +}
Expand description

singular-value decomposition of matrix reference

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/svd/trait.SVDInplace.html b/ndarray_linalg/svd/trait.SVDInplace.html new file mode 100644 index 00000000..8d7dbf1d --- /dev/null +++ b/ndarray_linalg/svd/trait.SVDInplace.html @@ -0,0 +1,33 @@ +SVDInplace in ndarray_linalg::svd - Rust + + + + + + +
pub trait SVDInplace {
+    type U;
+    type VT;
+    type Sigma;
+
+    fn svd_inplace(
        &mut self,
        calc_u: bool,
        calc_vt: bool
    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>; +}
Expand description

singular-value decomposition for mutable reference of matrix

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/svd/trait.SVDInto.html b/ndarray_linalg/svd/trait.SVDInto.html new file mode 100644 index 00000000..9e66b919 --- /dev/null +++ b/ndarray_linalg/svd/trait.SVDInto.html @@ -0,0 +1,33 @@ +SVDInto in ndarray_linalg::svd - Rust + + + + + + +
pub trait SVDInto {
+    type U;
+    type VT;
+    type Sigma;
+
+    fn svd_into(
        self,
        calc_u: bool,
        calc_vt: bool
    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>; +}
Expand description

singular-value decomposition

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/svddc/enum.UVTFlag.html b/ndarray_linalg/svddc/enum.UVTFlag.html new file mode 100644 index 00000000..232464cb --- /dev/null +++ b/ndarray_linalg/svddc/enum.UVTFlag.html @@ -0,0 +1,55 @@ +UVTFlag in ndarray_linalg::svddc - Rust + + + + + + +
#[repr(u8)]
+pub enum UVTFlag {
+    Full,
+    Some,
+    None,
+}
Expand description

Specifies how many of the columns of U and rows of Vᵀ are computed and returned.

+

For an input array of shape m×n, the following are computed:

+

Variants

Full

All m columns of U and all n rows of Vᵀ.

+

Some

The first min(m,n) columns of U and the first min(m,n) rows of Vᵀ.

+

None

No columns of U or rows of Vᵀ.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/svddc/index.html b/ndarray_linalg/svddc/index.html new file mode 100644 index 00000000..b03e0e53 --- /dev/null +++ b/ndarray_linalg/svddc/index.html @@ -0,0 +1,33 @@ +ndarray_linalg::svddc - Rust + + + + + + +
Expand description

Singular-value decomposition (SVD) by divide-and-conquer (?gesdd)

+

Enums

+

Specifies how many of the columns of U and rows of Vᵀ are computed and returned.

+

Traits

+

Singular-value decomposition of matrix (copying) by divide-and-conquer

+

Singular-value decomposition of matrix reference by divide-and-conquer

+

Singular-value decomposition of matrix by divide-and-conquer

+
+ \ No newline at end of file diff --git a/ndarray_linalg/svddc/sidebar-items.js b/ndarray_linalg/svddc/sidebar-items.js new file mode 100644 index 00000000..eb5618ec --- /dev/null +++ b/ndarray_linalg/svddc/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["UVTFlag","Specifies how many of the columns of U and rows of Vᵀ are computed and returned."]],"trait":[["SVDDC","Singular-value decomposition of matrix (copying) by divide-and-conquer"],["SVDDCInplace","Singular-value decomposition of matrix reference by divide-and-conquer"],["SVDDCInto","Singular-value decomposition of matrix by divide-and-conquer"]]}; \ No newline at end of file diff --git a/ndarray_linalg/svddc/trait.SVDDC.html b/ndarray_linalg/svddc/trait.SVDDC.html new file mode 100644 index 00000000..238edb46 --- /dev/null +++ b/ndarray_linalg/svddc/trait.SVDDC.html @@ -0,0 +1,33 @@ +SVDDC in ndarray_linalg::svddc - Rust + + + + + + +
pub trait SVDDC {
+    type U;
+    type VT;
+    type Sigma;
+
+    fn svddc(
        &self,
        uvt_flag: UVTFlag
    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>; +}
Expand description

Singular-value decomposition of matrix (copying) by divide-and-conquer

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/svddc/trait.SVDDCInplace.html b/ndarray_linalg/svddc/trait.SVDDCInplace.html new file mode 100644 index 00000000..b80ca545 --- /dev/null +++ b/ndarray_linalg/svddc/trait.SVDDCInplace.html @@ -0,0 +1,33 @@ +SVDDCInplace in ndarray_linalg::svddc - Rust + + + + + + +
pub trait SVDDCInplace {
+    type U;
+    type VT;
+    type Sigma;
+
+    fn svddc_inplace(
        &mut self,
        uvt_flag: UVTFlag
    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>; +}
Expand description

Singular-value decomposition of matrix reference by divide-and-conquer

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/svddc/trait.SVDDCInto.html b/ndarray_linalg/svddc/trait.SVDDCInto.html new file mode 100644 index 00000000..ed351c12 --- /dev/null +++ b/ndarray_linalg/svddc/trait.SVDDCInto.html @@ -0,0 +1,33 @@ +SVDDCInto in ndarray_linalg::svddc - Rust + + + + + + +
pub trait SVDDCInto {
+    type U;
+    type VT;
+    type Sigma;
+
+    fn svddc_into(
        self,
        uvt_flag: UVTFlag
    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>; +}
Expand description

Singular-value decomposition of matrix by divide-and-conquer

+

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/trace/index.html b/ndarray_linalg/trace/index.html new file mode 100644 index 00000000..56165926 --- /dev/null +++ b/ndarray_linalg/trace/index.html @@ -0,0 +1,28 @@ +ndarray_linalg::trace - Rust + + + + + + +
Expand description

Trace calculation

+

Traits

+
+ \ No newline at end of file diff --git a/ndarray_linalg/trace/sidebar-items.js b/ndarray_linalg/trace/sidebar-items.js new file mode 100644 index 00000000..efb9d982 --- /dev/null +++ b/ndarray_linalg/trace/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["Trace",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/trace/trait.Trace.html b/ndarray_linalg/trace/trait.Trace.html new file mode 100644 index 00000000..79aa685b --- /dev/null +++ b/ndarray_linalg/trace/trait.Trace.html @@ -0,0 +1,30 @@ +Trace in ndarray_linalg::trace - Rust + + + + + + +
pub trait Trace {
+    type Output;
+
+    fn trace(&self) -> Result<Self::Output>;
+}

Required Associated Types

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/triangular/enum.Diag.html b/ndarray_linalg/triangular/enum.Diag.html new file mode 100644 index 00000000..a42708b2 --- /dev/null +++ b/ndarray_linalg/triangular/enum.Diag.html @@ -0,0 +1,47 @@ +Diag in ndarray_linalg::triangular - Rust + + + + + + +
#[repr(u8)]
+pub enum Diag {
+    Unit,
+    NonUnit,
+}

Variants

Unit

NonUnit

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/triangular/index.html b/ndarray_linalg/triangular/index.html new file mode 100644 index 00000000..b5241b3f --- /dev/null +++ b/ndarray_linalg/triangular/index.html @@ -0,0 +1,32 @@ +ndarray_linalg::triangular - Rust + + + + + + +
Expand description

Methods for triangular matrices

+

Enums

+

Traits

+

solve a triangular system with upper triangular matrix

+

solve a triangular system with upper triangular matrix

+

solve a triangular system with upper triangular matrix

+
+ \ No newline at end of file diff --git a/ndarray_linalg/triangular/sidebar-items.js b/ndarray_linalg/triangular/sidebar-items.js new file mode 100644 index 00000000..4ef927d6 --- /dev/null +++ b/ndarray_linalg/triangular/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["Diag",""]],"trait":[["IntoTriangular",""],["SolveTriangular","solve a triangular system with upper triangular matrix"],["SolveTriangularInplace","solve a triangular system with upper triangular matrix"],["SolveTriangularInto","solve a triangular system with upper triangular matrix"]]}; \ No newline at end of file diff --git a/ndarray_linalg/triangular/trait.IntoTriangular.html b/ndarray_linalg/triangular/trait.IntoTriangular.html new file mode 100644 index 00000000..1afdd7cc --- /dev/null +++ b/ndarray_linalg/triangular/trait.IntoTriangular.html @@ -0,0 +1,28 @@ +IntoTriangular in ndarray_linalg::triangular - Rust + + + + + + +
pub trait IntoTriangular<T> {
+    fn into_triangular(self, uplo: UPLO) -> T;
+}

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/triangular/trait.SolveTriangular.html b/ndarray_linalg/triangular/trait.SolveTriangular.html new file mode 100644 index 00000000..7b033f03 --- /dev/null +++ b/ndarray_linalg/triangular/trait.SolveTriangular.html @@ -0,0 +1,29 @@ +SolveTriangular in ndarray_linalg::triangular - Rust + + + + + + +
pub trait SolveTriangular<A, S, D> where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
    D: Dimension
{ + fn solve_triangular(
        &self,
        uplo: UPLO,
        diag: Diag,
        b: &ArrayBase<S, D>
    ) -> Result<Array<A, D>>; +}
Expand description

solve a triangular system with upper triangular matrix

+

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/triangular/trait.SolveTriangularInplace.html b/ndarray_linalg/triangular/trait.SolveTriangularInplace.html new file mode 100644 index 00000000..a6fda910 --- /dev/null +++ b/ndarray_linalg/triangular/trait.SolveTriangularInplace.html @@ -0,0 +1,29 @@ +SolveTriangularInplace in ndarray_linalg::triangular - Rust + + + + + + +
pub trait SolveTriangularInplace<S, D> where
    S: DataMut,
    D: Dimension
{ + fn solve_triangular_inplace<'a>(
        &self,
        uplo: UPLO,
        diag: Diag,
        b: &'a mut ArrayBase<S, D>
    ) -> Result<&'a mut ArrayBase<S, D>>; +}
Expand description

solve a triangular system with upper triangular matrix

+

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/triangular/trait.SolveTriangularInto.html b/ndarray_linalg/triangular/trait.SolveTriangularInto.html new file mode 100644 index 00000000..4af19363 --- /dev/null +++ b/ndarray_linalg/triangular/trait.SolveTriangularInto.html @@ -0,0 +1,29 @@ +SolveTriangularInto in ndarray_linalg::triangular - Rust + + + + + + +
pub trait SolveTriangularInto<S, D> where
    S: DataMut,
    D: Dimension
{ + fn solve_triangular_into(
        &self,
        uplo: UPLO,
        diag: Diag,
        b: ArrayBase<S, D>
    ) -> Result<ArrayBase<S, D>>; +}
Expand description

solve a triangular system with upper triangular matrix

+

Required Methods

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/index.html b/ndarray_linalg/tridiagonal/index.html new file mode 100644 index 00000000..3de2bbbc --- /dev/null +++ b/ndarray_linalg/tridiagonal/index.html @@ -0,0 +1,39 @@ +ndarray_linalg::tridiagonal - Rust + + + + + + +
Expand description

Vectors as a Tridiagonal matrix +& +Methods for tridiagonal matrices

+

Structs

+

Represents the LU factorization of a tridiagonal matrix A as A = P*L*U.

+

Represents a tridiagonal matrix as 3 one-dimensional vectors.

+

Traits

+

An interface for calculating determinants of tridiagonal matrix refs.

+

An interface for making a Tridiagonal struct.

+

An interface for computing LU factorizations of tridiagonal matrix refs.

+

An interface for computing LU factorizations of tridiagonal matrices.

+

An interface for estimating the reciprocal condition number of tridiagonal matrix refs.

+

An interface for estimating the reciprocal condition number of tridiagonal matrices.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/sidebar-items.js b/ndarray_linalg/tridiagonal/sidebar-items.js new file mode 100644 index 00000000..d6da5003 --- /dev/null +++ b/ndarray_linalg/tridiagonal/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":[["LUFactorizedTridiagonal","Represents the LU factorization of a tridiagonal matrix `A` as `A = P*L*U`."],["Tridiagonal","Represents a tridiagonal matrix as 3 one-dimensional vectors."]],"trait":[["DeterminantTridiagonal","An interface for calculating determinants of tridiagonal matrix refs."],["ExtractTridiagonal","An interface for making a Tridiagonal struct."],["FactorizeTridiagonal","An interface for computing LU factorizations of tridiagonal matrix refs."],["FactorizeTridiagonalInto","An interface for computing LU factorizations of tridiagonal matrices."],["ReciprocalConditionNumTridiagonal","An interface for estimating the reciprocal condition number of tridiagonal matrix refs."],["ReciprocalConditionNumTridiagonalInto","An interface for estimating the reciprocal condition number of tridiagonal matrices."],["SolveTridiagonal",""],["SolveTridiagonalInplace",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/struct.LUFactorizedTridiagonal.html b/ndarray_linalg/tridiagonal/struct.LUFactorizedTridiagonal.html new file mode 100644 index 00000000..adcd4726 --- /dev/null +++ b/ndarray_linalg/tridiagonal/struct.LUFactorizedTridiagonal.html @@ -0,0 +1,112 @@ +LUFactorizedTridiagonal in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub struct LUFactorizedTridiagonal<A> where
    A: Scalar
{ + pub a: Tridiagonal<A>, + pub du2: Vec<A, Global>, + pub ipiv: Vec<i32, Global>, + /* private fields */ +}
Expand description

Represents the LU factorization of a tridiagonal matrix A as A = P*L*U.

+

Fields

a: Tridiagonal<A>

A tridiagonal matrix which consists of

+
    +
  • l : layout of raw matrix
  • +
  • dl: (n-1) multipliers that define the matrix L.
  • +
  • d : (n) diagonal elements of the upper triangular matrix U.
  • +
  • du: (n-1) elements of the first super-diagonal of U.
  • +
+
du2: Vec<A, Global>

(n-2) elements of the second super-diagonal of U.

+
ipiv: Vec<i32, Global>

The pivot indices that define the permutation matrix P.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Estimates the reciprocal of the condition number of the tridiagonal matrix in +1-norm. Read more

+

Estimates the reciprocal of the condition number of the tridiagonal matrix in +1-norm. Read more

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument. Read more

+

Solves a system of linear equations A^T * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument. Read more

+

Solves a system of linear equations A^H * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/struct.Tridiagonal.html b/ndarray_linalg/tridiagonal/struct.Tridiagonal.html new file mode 100644 index 00000000..aab291e2 --- /dev/null +++ b/ndarray_linalg/tridiagonal/struct.Tridiagonal.html @@ -0,0 +1,125 @@ +Tridiagonal in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub struct Tridiagonal<A> where
    A: Scalar
{ + pub l: MatrixLayout, + pub dl: Vec<A, Global>, + pub d: Vec<A, Global>, + pub du: Vec<A, Global>, +}
Expand description

Represents a tridiagonal matrix as 3 one-dimensional vectors.

+
[d0, u1,  0,   ...,       0,
+ l1, d1, u2,            ...,
+  0, l2, d2,
+ ...           ...,  u{n-1},
+  0,  ...,  l{n-1},  d{n-1},]

Fields

l: MatrixLayout

layout of raw matrix

+
dl: Vec<A, Global>

(n-1) sub-diagonal elements of matrix.

+
d: Vec<A, Global>

(n) diagonal elements of matrix.

+
du: Vec<A, Global>

(n-1) super-diagonal elements of matrix.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Computes the determinant of the matrix. +Unlike .det() of Determinant trait, this method +doesn’t returns the natural logarithm of the determinant +but the determinant itself. Read more

+

Computes the LU factorization A = P*L*U, where P is a permutation +matrix. Read more

+

Computes the LU factorization A = P*L*U, where P is a permutation +matrix. Read more

+

The returned type after indexing.

+

Performs the indexing (container[index]) operation. Read more

+

The returned type after indexing.

+

Performs the indexing (container[index]) operation. Read more

+

Performs the mutable indexing (container[index]) operation. Read more

+

Performs the mutable indexing (container[index]) operation. Read more

+

the value of norm

+

the one norm of a matrix (maximum column sum)

+

the infinity norm of a matrix (maximum row sum)

+

the Frobenius norm of a matrix (square root of sum of squares)

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. Read more

+

Solves a system of linear equations A * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument. Read more

+

Solves a system of linear equations A^T * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument. Read more

+

Solves a system of linear equations A^H * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the argument unchanged.

+

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/trait.DeterminantTridiagonal.html b/ndarray_linalg/tridiagonal/trait.DeterminantTridiagonal.html new file mode 100644 index 00000000..aabd44f5 --- /dev/null +++ b/ndarray_linalg/tridiagonal/trait.DeterminantTridiagonal.html @@ -0,0 +1,33 @@ +DeterminantTridiagonal in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub trait DeterminantTridiagonal<A: Scalar> {
+    fn det_tridiagonal(&self) -> Result<A>;
+}
Expand description

An interface for calculating determinants of tridiagonal matrix refs.

+

Required Methods

Computes the determinant of the matrix. +Unlike .det() of Determinant trait, this method +doesn’t returns the natural logarithm of the determinant +but the determinant itself.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/trait.ExtractTridiagonal.html b/ndarray_linalg/tridiagonal/trait.ExtractTridiagonal.html new file mode 100644 index 00000000..7f1e9c08 --- /dev/null +++ b/ndarray_linalg/tridiagonal/trait.ExtractTridiagonal.html @@ -0,0 +1,33 @@ +ExtractTridiagonal in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub trait ExtractTridiagonal<A: Scalar> {
+    fn extract_tridiagonal(&self) -> Result<Tridiagonal<A>>;
+}
Expand description

An interface for making a Tridiagonal struct.

+

Required Methods

Extract tridiagonal elements and layout of the raw matrix.

+

If the raw matrix has some non-tridiagonal elements, +they will be ignored.

+

The shape of raw matrix should be equal to or larger than (2, 2).

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonal.html b/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonal.html new file mode 100644 index 00000000..d4fbb570 --- /dev/null +++ b/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonal.html @@ -0,0 +1,31 @@ +FactorizeTridiagonal in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub trait FactorizeTridiagonal<A: Scalar> {
+    fn factorize_tridiagonal(&self) -> Result<LUFactorizedTridiagonal<A>>;
+}
Expand description

An interface for computing LU factorizations of tridiagonal matrix refs.

+

Required Methods

Computes the LU factorization A = P*L*U, where P is a permutation +matrix.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonalInto.html b/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonalInto.html new file mode 100644 index 00000000..a2dc89f6 --- /dev/null +++ b/ndarray_linalg/tridiagonal/trait.FactorizeTridiagonalInto.html @@ -0,0 +1,31 @@ +FactorizeTridiagonalInto in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub trait FactorizeTridiagonalInto<A: Scalar> {
+    fn factorize_tridiagonal_into(self) -> Result<LUFactorizedTridiagonal<A>>;
+}
Expand description

An interface for computing LU factorizations of tridiagonal matrices.

+

Required Methods

Computes the LU factorization A = P*L*U, where P is a permutation +matrix.

+

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonal.html b/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonal.html new file mode 100644 index 00000000..1928a255 --- /dev/null +++ b/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonal.html @@ -0,0 +1,37 @@ +ReciprocalConditionNumTridiagonal in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub trait ReciprocalConditionNumTridiagonal<A: Scalar> {
+    fn rcond_tridiagonal(&self) -> Result<A::Real>;
+}
Expand description

An interface for estimating the reciprocal condition number of tridiagonal matrix refs.

+

Required Methods

Estimates the reciprocal of the condition number of the tridiagonal matrix in +1-norm.

+

This method uses the LAPACK *gtcon routines, which estimate +self.inv_tridiagonal().opnorm_one() and then compute rcond = 1. / (self.opnorm_one() * self.inv_tridiagonal().opnorm_one()).

+
    +
  • If rcond is near 0., the matrix is badly conditioned.
  • +
  • If rcond is near 1., the matrix is well conditioned.
  • +
+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonalInto.html b/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonalInto.html new file mode 100644 index 00000000..4450664b --- /dev/null +++ b/ndarray_linalg/tridiagonal/trait.ReciprocalConditionNumTridiagonalInto.html @@ -0,0 +1,37 @@ +ReciprocalConditionNumTridiagonalInto in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub trait ReciprocalConditionNumTridiagonalInto<A: Scalar> {
+    fn rcond_tridiagonal_into(self) -> Result<A::Real>;
+}
Expand description

An interface for estimating the reciprocal condition number of tridiagonal matrices.

+

Required Methods

Estimates the reciprocal of the condition number of the tridiagonal matrix in +1-norm.

+

This method uses the LAPACK *gtcon routines, which estimate +self.inv_tridiagonal().opnorm_one() and then compute rcond = 1. / (self.opnorm_one() * self.inv_tridiagonal().opnorm_one()).

+
    +
  • If rcond is near 0., the matrix is badly conditioned.
  • +
  • If rcond is near 1., the matrix is well conditioned.
  • +
+

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/trait.SolveTridiagonal.html b/ndarray_linalg/tridiagonal/trait.SolveTridiagonal.html new file mode 100644 index 00000000..ce881c0b --- /dev/null +++ b/ndarray_linalg/tridiagonal/trait.SolveTridiagonal.html @@ -0,0 +1,51 @@ +SolveTridiagonal in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub trait SolveTridiagonal<A: Scalar, D: Dimension> {
+    fn solve_tridiagonal<S: Data<Elem = A>>(
        &self,
        b: &ArrayBase<S, D>
    ) -> Result<Array<A, D>>; + fn solve_tridiagonal_into<S: DataMut<Elem = A>>(
        &self,
        b: ArrayBase<S, D>
    ) -> Result<ArrayBase<S, D>>; + fn solve_t_tridiagonal<S: Data<Elem = A>>(
        &self,
        b: &ArrayBase<S, D>
    ) -> Result<Array<A, D>>; + fn solve_t_tridiagonal_into<S: DataMut<Elem = A>>(
        &self,
        b: ArrayBase<S, D>
    ) -> Result<ArrayBase<S, D>>; + fn solve_h_tridiagonal<S: Data<Elem = A>>(
        &self,
        b: &ArrayBase<S, D>
    ) -> Result<Array<A, D>>; + fn solve_h_tridiagonal_into<S: DataMut<Elem = A>>(
        &self,
        b: ArrayBase<S, D>
    ) -> Result<ArrayBase<S, D>>; +}

Required Methods

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result.

+

Solves a system of linear equations A * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result.

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result.

+

Solves a system of linear equations A^T * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result.

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result.

+

Solves a system of linear equations A^H * x = b with tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/tridiagonal/trait.SolveTridiagonalInplace.html b/ndarray_linalg/tridiagonal/trait.SolveTridiagonalInplace.html new file mode 100644 index 00000000..c3098ae6 --- /dev/null +++ b/ndarray_linalg/tridiagonal/trait.SolveTridiagonalInplace.html @@ -0,0 +1,42 @@ +SolveTridiagonalInplace in ndarray_linalg::tridiagonal - Rust + + + + + + +
pub trait SolveTridiagonalInplace<A: Scalar, D: Dimension> {
+    fn solve_tridiagonal_inplace<'a, S: DataMut<Elem = A>>(
        &self,
        b: &'a mut ArrayBase<S, D>
    ) -> Result<&'a mut ArrayBase<S, D>>; + fn solve_t_tridiagonal_inplace<'a, S: DataMut<Elem = A>>(
        &self,
        b: &'a mut ArrayBase<S, D>
    ) -> Result<&'a mut ArrayBase<S, D>>; + fn solve_h_tridiagonal_inplace<'a, S: DataMut<Elem = A>>(
        &self,
        b: &'a mut ArrayBase<S, D>
    ) -> Result<&'a mut ArrayBase<S, D>>; +}

Required Methods

Solves a system of linear equations A * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument.

+

Solves a system of linear equations A^T * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument.

+

Solves a system of linear equations A^H * x = b tridiagonal +matrix A, where A is self, b is the argument, and +x is the successful result. The value of x is also assigned to the +argument.

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/types/index.html b/ndarray_linalg/types/index.html new file mode 100644 index 00000000..3916c376 --- /dev/null +++ b/ndarray_linalg/types/index.html @@ -0,0 +1,30 @@ +ndarray_linalg::types - Rust + + + + + + +
Expand description

Basic types and their methods for linear algebra

+

Traits

+

Trait for primitive types which implements LAPACK subroutines

+

Type Definitions

+
+ \ No newline at end of file diff --git a/ndarray_linalg/types/sidebar-items.js b/ndarray_linalg/types/sidebar-items.js new file mode 100644 index 00000000..bb3fd64c --- /dev/null +++ b/ndarray_linalg/types/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["Lapack","Trait for primitive types which implements LAPACK subroutines"],["Scalar",""]],"type":[["c32",""],["c64",""]]}; \ No newline at end of file diff --git a/ndarray_linalg/types/trait.Lapack.html b/ndarray_linalg/types/trait.Lapack.html new file mode 100644 index 00000000..4adcd1f9 --- /dev/null +++ b/ndarray_linalg/types/trait.Lapack.html @@ -0,0 +1,27 @@ +Lapack in ndarray_linalg::types - Rust + + + + + + +
pub trait Lapack: OperatorNorm_ + QR_ + SVD_ + SVDDC_ + Solve_ + Solveh_ + Cholesky_ + Eig_ + Eigh_ + Triangular_ + Tridiagonal_ + Rcond_ + LeastSquaresSvdDivideConquer_ { }
Expand description

Trait for primitive types which implements LAPACK subroutines

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/types/trait.Scalar.html b/ndarray_linalg/types/trait.Scalar.html new file mode 100644 index 00000000..4f47bc1b --- /dev/null +++ b/ndarray_linalg/types/trait.Scalar.html @@ -0,0 +1,77 @@ +Scalar in ndarray_linalg::types - Rust + + + + + + +
pub trait Scalar: 'static + NumAssign + FromPrimitive + NumCast + Neg<Output = Self> + Copy + Clone + Display + Debug + LowerExp + UpperExp + Sum<Self> + Product<Self> + Serialize + for<'de> Deserialize<'de> {
+    type Real: Scalar + NumOps<Self::Real, Self::Real> + Float
    where
        <Self::Real as Scalar>::Real == Self::Real,
        <Self::Real as Scalar>::Complex == Self::Complex
; + type Complex: Scalar + NumOps<Self::Real, Self::Complex> + NumOps<Self::Complex, Self::Complex>
    where
        <Self::Complex as Scalar>::Real == Self::Real,
        <Self::Complex as Scalar>::Complex == Self::Complex
; + +
Show 37 methods fn real<T>(re: T) -> Self::Real
    where
        T: ToPrimitive
; + fn complex<T>(re: T, im: T) -> Self::Complex
    where
        T: ToPrimitive
; + fn from_real(re: Self::Real) -> Self; + fn add_real(self, re: Self::Real) -> Self; + fn sub_real(self, re: Self::Real) -> Self; + fn mul_real(self, re: Self::Real) -> Self; + fn div_real(self, re: Self::Real) -> Self; + fn add_complex(self, im: Self::Complex) -> Self::Complex; + fn sub_complex(self, im: Self::Complex) -> Self::Complex; + fn mul_complex(self, im: Self::Complex) -> Self::Complex; + fn div_complex(self, im: Self::Complex) -> Self::Complex; + fn pow(self, n: Self) -> Self; + fn powi(self, n: i32) -> Self; + fn powf(self, n: Self::Real) -> Self; + fn powc(self, n: Self::Complex) -> Self::Complex; + fn re(&self) -> Self::Real; + fn im(&self) -> Self::Real; + fn as_c(&self) -> Self::Complex; + fn conj(&self) -> Self; + fn abs(self) -> Self::Real; + fn square(self) -> Self::Real; + fn sqrt(self) -> Self; + fn exp(self) -> Self; + fn ln(self) -> Self; + fn sin(self) -> Self; + fn cos(self) -> Self; + fn tan(self) -> Self; + fn asin(self) -> Self; + fn acos(self) -> Self; + fn atan(self) -> Self; + fn sinh(self) -> Self; + fn cosh(self) -> Self; + fn tanh(self) -> Self; + fn asinh(self) -> Self; + fn acosh(self) -> Self; + fn atanh(self) -> Self; + fn rand(rng: &mut impl Rng) -> Self; +
}

Required Associated Types

Required Methods

Create a new real number

+

Create a new complex number

+

Real part

+

Imaginary part

+

As a complex number

+

Complex conjugate

+

Absolute value

+

Sqaure of absolute value

+

Generate an random number from +rand::distributions::Standard

+

Implementations on Foreign Types

Implementors

+ \ No newline at end of file diff --git a/ndarray_linalg/types/type.c32.html b/ndarray_linalg/types/type.c32.html new file mode 100644 index 00000000..444cc852 --- /dev/null +++ b/ndarray_linalg/types/type.c32.html @@ -0,0 +1,26 @@ +c32 in ndarray_linalg::types - Rust + + + + + + +
+

Type Definition ndarray_linalg::types::c32

source · []
pub type c32 = Complex<f32>;
+ \ No newline at end of file diff --git a/ndarray_linalg/types/type.c64.html b/ndarray_linalg/types/type.c64.html new file mode 100644 index 00000000..f54291ac --- /dev/null +++ b/ndarray_linalg/types/type.c64.html @@ -0,0 +1,26 @@ +c64 in ndarray_linalg::types - Rust + + + + + + +
+

Type Definition ndarray_linalg::types::c64

source · []
pub type c64 = Complex<f64>;
+ \ No newline at end of file diff --git a/normalize.css b/normalize.css new file mode 100644 index 00000000..469959f1 --- /dev/null +++ b/normalize.css @@ -0,0 +1,2 @@ + /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} \ No newline at end of file diff --git a/noscript.css b/noscript.css new file mode 100644 index 00000000..d850bb38 --- /dev/null +++ b/noscript.css @@ -0,0 +1 @@ + #main-content .attributes{margin-left:0 !important;}#copy-path{display:none;}.sub{display:none;} \ No newline at end of file diff --git a/rust-logo.svg b/rust-logo.svg new file mode 100644 index 00000000..62424d8f --- /dev/null +++ b/rust-logo.svg @@ -0,0 +1,61 @@ + + + diff --git a/rustdoc.css b/rustdoc.css new file mode 100644 index 00000000..26904c7b --- /dev/null +++ b/rustdoc.css @@ -0,0 +1 @@ + @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("https://github.com/FiraSans-Regular.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("https://github.com/FiraSans-Medium.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("https://github.com/SourceSerif4-Regular.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("https://github.com/SourceSerif4-It.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("https://github.com/SourceSerif4-Bold.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("https://github.com/SourceCodePro-Regular.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("https://github.com/SourceCodePro-It.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("https://github.com/SourceCodePro-Semibold.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'NanumBarunGothic';src:url("https://github.com/NanumBarunGothic.ttf.woff2") format("woff2");font-display:swap;unicode-range:U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF;}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:1rem/1.5 "Source Serif 4",NanumBarunGothic,serif;margin:0;position:relative;overflow-wrap:break-word;overflow-wrap:anywhere;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5rem;}h2{font-size:1.375rem;}h3{font-size:1.25rem;}h1,h2,h3,h4,h5,h6{font-weight:500;}h1,h2,h3,h4{margin:20px 0 15px 0;padding-bottom:6px;}.docblock h3,.docblock h4,h5,h6{margin:15px 0 5px 0;}h1.fqn{margin:0;padding:0;}.main-heading{display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:6px;margin-bottom:15px;}.main-heading a:hover{text-decoration:underline;}#toggle-all-docs{text-decoration:none;}h2,.top-doc h3,.top-doc h4{border-bottom:1px solid;}h3.code-header{font-size:1.125rem;}h4.code-header{font-size:1rem;}.code-header{font-weight:600;border-bottom-style:none;margin:0;padding:0;margin-top:0.6em;margin-bottom:0.4em;}.impl,.impl-items .method,.methods .method,.impl-items .type,.methods .type,.impl-items .associatedconstant,.methods .associatedconstant,.impl-items .associatedtype,.methods .associatedtype{flex-basis:100%;font-weight:600;position:relative;}div.impl-items>div{padding-left:0;}h1,h2,h3,h4,h5,h6,.sidebar,.mobile-topbar,a.source,.search-input,.search-results .result-name,.content table td:first-child>a,.item-left>a,.out-of-band,span.since,#source-sidebar,#sidebar-toggle,details.rustdoc-toggle>summary::before,div.impl-items>div:not(.docblock):not(.item-info),.content ul.crate a.crate,a.srclink,#main-content>ul.docblock>li>a{font-family:"Fira Sans",Arial,NanumBarunGothic,sans-serif;}ol,ul{padding-left:24px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.625em;}p{margin:0 0 .75em 0;}summary{outline:none;}td,th{padding:0;}table{border-collapse:collapse;}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;}button{padding:1px 6px;}.rustdoc{display:flex;flex-direction:row;flex-wrap:nowrap;}main{position:relative;flex-grow:1;padding:10px 15px 40px 45px;min-width:0;}.source main{padding:15px;}.width-limiter{max-width:960px;margin-right:auto;}.source .width-limiter{max-width:unset;}details:not(.rustdoc-toggle) summary{margin-bottom:.6em;}code,pre,a.test-arrow,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.125em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;}.docblock.item-decl{margin-left:0;}.item-decl pre{overflow-x:auto;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{max-width:none;overflow:visible;margin-left:0px;}nav.sub{position:relative;font-size:1rem;}.sub-container{display:flex;flex-direction:row;flex-wrap:nowrap;}.sub-logo-container{display:none;margin-right:20px;}.source .sub-logo-container{display:block;}.source .sub-logo-container>img{height:60px;width:60px;object-fit:contain;}.sidebar{font-size:0.875rem;width:250px;min-width:200px;overflow-y:scroll;position:sticky;height:100vh;top:0;left:0;}.sidebar-elems,.sidebar>.location{padding-left:24px;}.sidebar .location{overflow-wrap:anywhere;}.rustdoc.source .sidebar{width:50px;min-width:0px;max-width:300px;flex-grow:0;flex-shrink:0;flex-basis:auto;border-right:1px solid;overflow-x:hidden;overflow-y:hidden;}.rustdoc.source .sidebar .sidebar-logo{display:none;}.source .sidebar>*:not(#sidebar-toggle){opacity:0;visibility:hidden;}.source-sidebar-expanded .source .sidebar{overflow-y:auto;}.source-sidebar-expanded .source .sidebar>*:not(#sidebar-toggle){opacity:1;visibility:visible;}#all-types{margin-top:1em;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.hidden{display:none !important;}.sidebar .logo-container{display:flex;margin-top:10px;margin-bottom:10px;justify-content:center;}.version{overflow-wrap:break-word;}.logo-container>img{height:100px;width:100px;}.location:empty{border:none;}.location a:first-of-type{font-weight:500;}.block{padding:0;}.block ul,.block li{padding:0;margin:0;list-style:none;}.block a,h2.location a{display:block;padding:0.25rem;margin-left:-0.25rem;text-overflow:ellipsis;overflow:hidden;}.sidebar h2{border-bottom:none;font-weight:500;padding:0;margin:0;margin-top:0.7rem;margin-bottom:0.7rem;}.sidebar h3{font-size:1.125rem;font-weight:500;padding:0;margin:0;}.sidebar-elems .block{margin-bottom:2em;}.sidebar-elems .block li a{white-space:nowrap;}.mobile-topbar{display:none;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc .example-wrap{display:inline-flex;margin-bottom:10px;}.example-wrap{position:relative;width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;padding:13px 8px;text-align:right;border-top-left-radius:5px;border-bottom-left-radius:5px;}.example-wrap>pre.rust a:hover{text-decoration:underline;}.line-numbers{text-align:right;}.rustdoc:not(.source) .example-wrap>pre:not(.line-number){width:100%;overflow-x:auto;}.rustdoc:not(.source) .example-wrap>pre.line-numbers{width:auto;overflow-x:visible;}.rustdoc .example-wrap>pre{margin:0;}#search{position:relative;}.search-loading{text-align:center;}#results>table{width:100%;table-layout:fixed;}.content>.example-wrap pre.line-numbers{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short{overflow-wrap:break-word;overflow-wrap:anywhere;}.docblock-short p{display:inline;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock>:not(pre)>code,.docblock-short>:not(pre)>code{white-space:pre-wrap;}.top-doc .docblock h2{font-size:1.375rem;}.top-doc .docblock h3{font-size:1.25;}.top-doc .docblock h4,.top-doc .docblock h5{font-size:1.125rem;}.top-doc .docblock h6{font-size:1rem;}.docblock h5{font-size:1rem;}.docblock h6{font-size:0.875rem;}.docblock{margin-left:24px;position:relative;}.docblock>:not(.information):not(.more-examples-toggle){max-width:100%;overflow-x:auto;}.content .out-of-band{flex-grow:0;font-size:1.125rem;font-weight:normal;float:right;}.method>.code-header,.trait-impl>.code-header{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{flex-grow:1;margin:0px;padding:0px;overflow-wrap:break-word;overflow-wrap:anywhere;}.in-band>code,.in-band>.code-header{display:inline-block;}#main-content{position:relative;}#main-content>.since{top:inherit;font-family:"Fira Sans",Arial,sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.125rem;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);overflow-x:auto;display:block;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content>.methods>.method{font-size:1rem;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.875rem;}.content .methods>div:not(.notable-traits):not(.method){margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.item-info{display:block;}.content .item-info code{font-size:0.875rem;}.content .item-info{position:relative;margin-left:24px;}.sub-variant>div>.item-info{margin-top:initial;}.content .impl-items .docblock,.content .impl-items .item-info{margin-bottom:.6em;}.content .impl-items>.item-info{margin-left:40px;}.methods>.item-info,.content .impl-items>.item-info{margin-top:-8px;}.impl-items{flex-basis:100%;}#main-content>.item-info{margin-top:0;margin-left:0;}nav.sub{flex-grow:1;margin-bottom:25px;}.source nav.sub{margin-left:32px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}a{text-decoration:none;background:transparent;}.small-section-header{display:flex;justify-content:space-between;position:relative;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor,.method.trait-impl:hover>.anchor,.type.trait-impl:hover>.anchor,.associatedconstant.trait-impl:hover>.anchor,.associatedtype.trait-impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:-0.5em;background:none !important;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-15px;padding-right:8px;}h2.small-section-header>.anchor{padding-right:6px;}.anchor::before{content:'§';}.docblock a:not(.srclink):not(.test-arrow):not(.scrape-help):hover,.docblock-short a:not(.srclink):not(.test-arrow):not(.scrape-help):hover,.item-info a{text-decoration:underline;}.block a.current.crate{font-weight:500;}table,.item-table{overflow-wrap:break-word;}.item-table{display:table;}.item-row{display:table-row;}.item-left,.item-right{display:table-cell;}.item-left{padding-right:1.25rem;}.search-container{position:relative;display:flex;height:34px;}.search-container>*{height:100%;}.search-results-title{display:inline;}#search-settings{font-size:1.5rem;font-weight:500;margin-bottom:20px;}#crate-search{min-width:115px;margin-top:5px;margin-left:0.25em;padding-left:0.3125em;padding-right:23px;border:1px solid;border-radius:4px;outline:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;background-image:url("https://github.com/down-arrow.svg");}.search-container{margin-top:4px;}.search-input{-webkit-appearance:none;-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:1px solid;border-radius:2px;padding:8px;font-size:1rem;transition:border-color 300ms ease;width:100%;}.search-results{display:none;padding-bottom:2em;}.search-results.active{display:block;clear:both;}.search-results .desc>span{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results>a{display:block;width:100%;margin-left:2px;margin-right:2px;border-bottom:1px solid #aaa3;}.search-results>a>div{display:flex;flex-flow:row wrap;}.search-results .result-name,.search-results div.desc,.search-results .result-description{width:50%;}.search-results .result-name{padding-right:1em;}.search-results .result-name>span{display:inline-block;margin:0;font-weight:normal;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;margin-right:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:1.125rem;}#help span.top{text-align:center;display:block;margin:10px 0;border-bottom:1px solid;padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:0 20px 20px 17px;;}.item-info .stab{display:inline-block;}.stab{padding:3px;margin-bottom:5px;font-size:0.875rem;font-weight:normal;}.stab p{display:inline;}.stab .emoji{font-size:1.25rem;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.module-item .stab,.import-item .stab{border-radius:3px;display:inline-block;font-size:0.875rem;line-height:1.2;margin-bottom:0;margin-left:0.3125em;padding:2px;vertical-align:text-bottom;}.module-item.unstable,.import-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;}.rightside{padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink,.methods .srclink{font-weight:normal;font-size:1rem;}.rightside{float:right;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;visibility:hidden;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:1.375rem;top:5px;right:5px;z-index:1;}.example-wrap:hover .test-arrow{visibility:visible;}a.test-arrow:hover{text-decoration:none;}.code-attribute{font-weight:300;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:1.25rem;}h3.variant{font-weight:600;font-size:1.125rem;margin-bottom:10px;border-bottom:none;}.sub-variant h4{font-size:1rem;font-weight:400;border-bottom:none;margin-top:0;margin-bottom:0;}.sub-variant{margin-left:24px;margin-bottom:40px;}.sub-variant>.sub-variant-field{margin-left:24px;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}:target>code,:target>.code-header{opacity:1;}:target{padding-right:3px;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip::after{display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;font-size:1rem;}.tooltip.ignore::after{content:"This example is not tested";}.tooltip.compile_fail::after{content:"This example deliberately fails to compile";}.tooltip.should_panic::after{content:"This example panics";}.tooltip.edition::after{content:"This code runs with edition " attr(data-edition);}.tooltip::before{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;display:none;}.tooltip:hover::before,.tooltip:hover::after{display:inline;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:1.25rem;}.notable-traits-tooltip{display:inline-block;cursor:pointer;}.notable-traits:hover .notable-traits-tooltiptext,.notable-traits .notable-traits-tooltiptext.force-tooltip{display:inline-block;}.notable-traits .notable-traits-tooltiptext{display:none;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;z-index:10;font-size:1rem;cursor:default;position:absolute;border:1px solid;}.notable-traits-tooltip::after{content:"\00a0\00a0\00a0";}.notable-traits .notable,.notable-traits .docblock{margin:0;}.notable-traits .notable{margin:0;margin-bottom:13px;font-size:1.1875rem;font-weight:600;display:block;}.notable-traits .docblock code.content{margin:0;padding:0;font-size:1.25rem;}pre.rust.rust-example-rendered{position:relative;}pre.rust{tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>button{float:left;width:33.3%;text-align:center;font-size:1.125rem;cursor:pointer;border:0;border-top:2px solid;}#titles>button:first-child:last-child{margin-right:1px;width:calc(100% - 1px);}#titles>button:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>button>div.count{display:inline-block;font-size:1rem;}.notable-traits{cursor:pointer;z-index:2;margin-left:5px;}#sidebar-toggle{position:sticky;top:0;left:0;cursor:pointer;font-weight:bold;font-size:1.25rem;border-bottom:1px solid;display:flex;height:40px;justify-content:center;align-items:center;z-index:10;}#source-sidebar{width:100%;z-index:1;overflow:auto;}#source-sidebar>.title{font-size:1.5rem;text-align:center;border-bottom:1px solid;margin-bottom:6px;}#settings-menu,#help-button{margin-left:4px;outline:none;}#copy-path{height:34px;}#settings-menu>a,#help-button,#copy-path{padding:5px;width:33px;border:1px solid;border-radius:2px;cursor:pointer;}#settings-menu{padding:0;}#settings-menu>a{padding:5px;width:100%;height:100%;display:block;}@keyframes rotating{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}#settings-menu.rotate>a img{animation:rotating 2s linear infinite;}#help-button{font-family:"Fira Sans",Arial,sans-serif;text-align:center;font-size:20px;padding-top:2px;}#copy-path{background:initial;margin-left:10px;padding:0;padding-left:2px;border:0;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px 8px;text-align:center;background:rgba(0,0,0,0);overflow-wrap:normal;}#theme-choices>button:not(:first-child){border-top:1px solid;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:1rem;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:1.125rem;display:block;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main-content>ul{padding-left:10px;}#main-content>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.625rem;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}details.rustdoc-toggle>summary.hideme{cursor:pointer;}details.rustdoc-toggle>summary{list-style:none;}details.rustdoc-toggle>summary::-webkit-details-marker,details.rustdoc-toggle>summary::marker{display:none;}details.rustdoc-toggle>summary.hideme>span{margin-left:9px;}details.rustdoc-toggle>summary::before{content:"";cursor:pointer;width:16px;height:16px;background-repeat:no-repeat;background-position:top left;display:inline-block;vertical-align:middle;opacity:.5;}details.rustdoc-toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.rustdoc-toggle>summary.hideme::after{content:"";}details.rustdoc-toggle>summary:focus::before,details.rustdoc-toggle>summary:hover::before{opacity:1;}details.rustdoc-toggle.top-doc>summary,details.rustdoc-toggle.top-doc>summary::before,details.rustdoc-toggle.non-exhaustive>summary,details.rustdoc-toggle.non-exhaustive>summary::before{font-family:'Fira Sans';font-size:1rem;}details.non-exhaustive{margin-bottom:8px;}details.rustdoc-toggle>summary.hideme::before{position:relative;}details.rustdoc-toggle>summary:not(.hideme)::before{position:absolute;left:-24px;top:4px;}.impl-items>details.rustdoc-toggle>summary:not(.hideme)::before{position:absolute;left:-24px;}details.rustdoc-toggle[open] >summary.hideme{position:absolute;}details.rustdoc-toggle{position:relative;}details.rustdoc-toggle[open] >summary.hideme>span{display:none;}details.undocumented[open] >summary::before,details.rustdoc-toggle[open] >summary::before,details.rustdoc-toggle[open] >summary.hideme::before{background-image:url("https://github.com/toggle-minus.svg");}details.undocumented>summary::before,details.rustdoc-toggle>summary::before{background-image:url("https://github.com/toggle-plus.svg");}details.rustdoc-toggle[open] >summary::before,details.rustdoc-toggle[open] >summary.hideme::before{width:16px;height:16px;background-repeat:no-repeat;background-position:top left;display:inline-block;content:"";}details.rustdoc-toggle[open] >summary::after,details.rustdoc-toggle[open] >summary.hideme::after{content:"Collapse";}@media (min-width:701px){.docblock>.information:first-child>.tooltip{margin-top:16px;}.source-sidebar-expanded .source .sidebar+main .width-limiter .sub-logo-container.rust-logo{display:none;}.source-sidebar-expanded .source .sidebar{width:300px;}}@media (max-width:700px){*[id]{scroll-margin-top:45px;}.rustdoc{padding-top:0px;display:block;}main{padding-left:15px;padding-top:0px;}.rustdoc,.main-heading{flex-direction:column;}.content .out-of-band{text-align:left;margin-left:initial;padding:initial;}.content .out-of-band .since::before{content:"Since ";}#copy-path{display:none;}.sidebar .sidebar-logo,.sidebar .location{display:none;}.sidebar-elems{margin-top:1em;}.sidebar{position:fixed;top:45px;left:-1000px;margin-left:0;background-color:rgba(0,0,0,0);margin:0;padding:0;z-index:11;height:calc(100vh - 45px);}.source main,.source .sidebar{top:0;padding:0;}.sidebar.shown,.source-sidebar-expanded .source .sidebar,.sidebar:focus-within{left:0;}.rustdoc.source>.sidebar{position:fixed;margin:0;z-index:11;width:0;}.mobile-topbar .location a{padding:0;margin:0;}.mobile-topbar .location{border:none;padding:0;margin:auto 0.5em auto auto;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:24px;}.mobile-topbar .logo-container{max-height:45px;}.mobile-topbar .logo-container>img{max-width:35px;max-height:35px;margin-left:20px;margin-top:5px;margin-bottom:5px;}.mobile-topbar{display:flex;flex-direction:row;position:sticky;z-index:10;font-size:2rem;height:45px;width:100%;left:0;top:0;}.source .mobile-topbar{display:none;}.sidebar-menu-toggle{width:45px;font-size:32px;border:none;}.source nav:not(.sidebar).sub{margin-left:32px;}.content{margin-left:0px;}.source .content{margin-top:10px;}#search{margin-left:0;padding:0;}.anchor{display:none !important;}.notable-traits{position:absolute;left:-22px;top:24px;}#titles>button>div.count{float:left;width:100%;}#titles{height:50px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}#main-content>details.rustdoc-toggle>summary::before,#main-content>div>details.rustdoc-toggle>summary::before{left:-11px;}#sidebar-toggle{position:fixed;left:1px;top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;z-index:10;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;border:1px solid;border-left:0;}.source-sidebar-expanded #sidebar-toggle{left:unset;top:unset;width:unset;border-top-right-radius:unset;border-bottom-right-radius:unset;}#source-sidebar{z-index:11;}#main-content>.line-numbers{margin-top:0;}.notable-traits .notable-traits-tooltiptext{left:0;top:100%;}#help-button{display:none;}.item-table{display:block;}.item-row{display:flex;flex-flow:column wrap;}.item-left,.item-right{width:100%;}.search-results>a{border-bottom:1px solid #aaa9;padding:5px 0px;}.search-results .result-name,.search-results div.desc,.search-results .result-description{width:100%;}.search-results div.desc,.search-results .result-description,.item-right{padding-left:2em;}.source-sidebar-expanded .source .sidebar{max-width:100vw;width:100vw;}details.rustdoc-toggle:not(.top-doc)>summary{margin-left:10px;}.impl-items>details.rustdoc-toggle>summary:not(.hideme)::before,#main-content>details.rustdoc-toggle:not(.top-doc)>summary::before,#main-content>div>details.rustdoc-toggle>summary::before{left:-11px;}}@media print{nav.sub,.content .out-of-band{display:none;}}@media (max-width:464px){#titles,#titles>button{height:73px;}#main-content>table:not(.table-display) td{word-break:break-word;width:50%;}#crate-search{border-radius:4px;}.docblock{margin-left:12px;}.docblock code{overflow-wrap:break-word;overflow-wrap:anywhere;}.sub-container{flex-direction:column;}.sub-logo-container{align-self:center;}.source .sub-logo-container>img{height:35px;width:35px;}#sidebar-toggle{top:10px;}.source-sidebar-expanded #sidebar-toggle{top:unset;}}.method-toggle summary,.implementors-toggle summary,.impl{margin-bottom:0.75em;}.method-toggle[open]{margin-bottom:2em;}.implementors-toggle[open]{margin-bottom:2em;}#trait-implementations-list .method-toggle,#synthetic-implementations-list .method-toggle,#blanket-implementations-list .method-toggle{margin-bottom:1em;}.scraped-example-list .scrape-help{margin-left:10px;padding:0 4px;font-weight:normal;font-size:12px;position:relative;bottom:1px;background:transparent;border-width:1px;border-style:solid;border-radius:50px;}.scraped-example-title{font-family:'Fira Sans';}.scraped-example .code-wrapper{position:relative;display:flex;flex-direction:row;flex-wrap:wrap;width:100%;}.scraped-example:not(.expanded) .code-wrapper{max-height:240px;}.scraped-example:not(.expanded) .code-wrapper pre{overflow-y:hidden;max-height:240px;padding-bottom:0;}.scraped-example:not(.expanded) .code-wrapper pre.line-numbers{overflow-x:hidden;}.scraped-example .code-wrapper .prev{position:absolute;top:0.25em;right:2.25em;z-index:100;cursor:pointer;}.scraped-example .code-wrapper .next{position:absolute;top:0.25em;right:1.25em;z-index:100;cursor:pointer;}.scraped-example .code-wrapper .expand{position:absolute;top:0.25em;right:0.25em;z-index:100;cursor:pointer;}.scraped-example:not(.expanded) .code-wrapper:before{content:" ";width:100%;height:5px;position:absolute;z-index:100;top:0;}.scraped-example:not(.expanded) .code-wrapper:after{content:" ";width:100%;height:5px;position:absolute;z-index:100;bottom:0;}.scraped-example .code-wrapper .line-numbers{margin:0;padding:14px 0;}.scraped-example .code-wrapper .line-numbers span{padding:0 14px;}.scraped-example .code-wrapper .example-wrap{flex:1;overflow-x:auto;overflow-y:hidden;margin-bottom:0;}.scraped-example:not(.expanded) .code-wrapper .example-wrap{overflow-x:hidden;}.scraped-example .code-wrapper .example-wrap pre.rust{overflow-x:inherit;width:inherit;overflow-y:hidden;}.more-examples-toggle{max-width:calc(100% + 25px);margin-top:10px;margin-left:-25px;}.more-examples-toggle .hide-more{margin-left:25px;margin-bottom:5px;cursor:pointer;}.more-examples-toggle summary,.more-examples-toggle .hide-more{font-family:'Fira Sans';}.more-scraped-examples{margin-left:5px;display:flex;flex-direction:row;}.more-scraped-examples-inner{width:calc(100% - 20px);}.toggle-line{align-self:stretch;margin-right:10px;margin-top:5px;padding:0 4px;cursor:pointer;}.toggle-line-inner{min-width:2px;height:100%;}.more-scraped-examples .scraped-example{margin-bottom:20px;}.more-scraped-examples .scraped-example:last-child{margin-bottom:0;}.example-links a{margin-top:20px;font-family:'Fira Sans';}.example-links ul{margin-bottom:0;} \ No newline at end of file diff --git a/search-index.js b/search-index.js new file mode 100644 index 00000000..2a3522d4 --- /dev/null +++ b/search-index.js @@ -0,0 +1,6 @@ +var searchIndex = JSON.parse('{\ +"lax":{"doc":"Linear Algebra eXtension (LAX)","t":[13,8,4,8,4,8,13,13,13,13,3,8,3,8,13,13,13,13,4,13,13,8,6,8,8,8,3,8,8,8,13,4,13,8,3,8,4,4,13,13,12,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,10,10,10,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,10,10,12,11,12,0,10,10,10,10,11,11,10,10,10,12,10,10,12,12,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,8,4,13,13,13,6,10,11,11,11,11,11,11,11,11,11,11,11,12,12,13,13,4,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,11,11,5,5,11,11,11,11,12,12,12,12],"n":["Calc","Cholesky_","Diag","Eig_","EigenVectorFlag","Eigh_","Frobenius","Full","Hermite","Infinity","LUFactorizedTridiagonal","Lapack","LeastSquaresOutput","LeastSquaresSvdDivideConquer_","Lower","No","NonUnit","None","NormType","Not","One","OperatorNorm_","Pivot","QR_","Rcond_","SVDDC_","SVDOutput","SVD_","Solve_","Solveh_","Some","Transpose","Transpose","Triangular_","Tridiagonal","Tridiagonal_","UPLO","UVTFlag","Unit","Upper","a","as_ptr","as_ptr","as_ptr","as_ptr","bk","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","cholesky","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","d","dl","du","du2","eig","eigh","eigh_generalized","eq","eq","eq","eq","error","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","householder","index","index","index_mut","index_mut","into","into","into","into","into","into","into","into","into","into","inv","inv_cholesky","invh","ipiv","is_calc","l","layout","least_squares","least_squares_nrhs","lu","lu_tridiagonal","ne","ne","opnorm","q","qr","rank","rcond","rcond_tridiagonal","s","singular_values","solve","solve_cholesky","solve_triangular","solve_tridiagonal","solveh","svd","svddc","t","then","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","transpose","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","u","vt","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","AsLapackResult","Error","InvalidShape","LapackComputationalFailure","LapackInvalidValue","Result","as_lapack_result","borrow","borrow_mut","fmt","fmt","from","into","to_string","try_from","try_into","type_id","vzip","return_code","return_code","C","F","MatrixLayout","borrow","borrow_mut","clone","clone_into","eq","fmt","from","into","is_empty","lda","len","ne","resized","same_order","size","square_transpose","t","to_owned","toggle_order","transpose","transpose_over","try_from","try_into","type_id","vzip","col","lda","lda","row"],"q":["lax","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","lax::error","","","","","","","","","","","","","","","","","","lax::error::Error","","lax::layout","","","","","","","","","","","","","","","","","","","","","","","","","","","","lax::layout::MatrixLayout","","",""],"d":["","","","Wraps *geev for general matrices","Flag for calculating eigenvectors or not","","","All m columns of U and all n rows of Vᵀ.","","","Represents the LU factorization of a tridiagonal matrix A …","Trait for primitive types which implements LAPACK …","Result of LeastSquares","Wraps *gelsd","","","","No columns of U or rows of Vᵀ.","","","","","","","","","Result of SVD","Wraps *gesvd","","","The first min(m,n) columns of U and the first min(m,n) …","","","Wraps *trtri and *trtrs","Represents a tridiagonal matrix as 3 one-dimensional …","Wraps *gttrf, *gtcon and *gttrs","Upper/Lower specification for seveal usages","Specifies how many of the columns of U and rows of Vᵀ …","","","A tridiagonal matrix which consists of","To use Fortran LAPACK API in lapack-sys crate","To use Fortran LAPACK API in lapack-sys crate","To use Fortran LAPACK API in lapack-sys crate","To use Fortran LAPACK API in lapack-sys crate","Bunch-Kaufman: wrapper of *sytrf and *hetrf","","","","","","","","","","","","","","","","","","","","","Cholesky: wrapper of *potrf","","","","","","","","","","","","","","","","","(n) diagonal elements of matrix.","(n-1) sub-diagonal elements of matrix.","(n-1) super-diagonal elements of matrix.","(n-2) elements of the second super-diagonal of U.","Calculate Right eigenvalue","Wraps *syev for real and *heev for complex","Wraps *sygv for real and *hegv for complex","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Execute Householder reflection as the first step of …","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","Wrapper of *potri","Wrapper of *sytri and *hetri","The pivot indices that define the permutation matrix P.","","layout of raw matrix","Memory layout of matrices","","","Computes the LU factorization of a general m x n matrix a …","Computes the LU factorization of a tridiagonal m x n …","","","","Reconstruct Q-matrix from Householder-reflectors","Execute QR-decomposition at once","The rank of the input matrix A","Estimates the the reciprocal of the condition number of …","","diagonal values","singular values","","Wrapper of *potrs","","","Wrapper of *sytrs and *hetrs","Calculate singular value decomposition $ A = U \\\\Sigma V^T $","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Unitary matrix for destination space","Unitary matrix for departure space","","","","","","","","","","","","","Strides of the array is not supported","","","","","","","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","","","In-place transpose of a square matrix by keeping F/C layout","Transpose without changing memory representation","","","Out-place transpose for general matrix","Out-place transpose for general matrix","","","","","","","",""],"i":[1,0,0,0,0,0,2,3,4,2,0,0,0,0,5,4,6,3,0,1,2,0,0,0,0,0,0,0,0,0,3,0,4,0,0,0,0,0,6,5,7,5,4,2,1,8,9,10,3,6,11,7,5,4,2,1,9,10,3,6,11,7,5,4,2,1,12,3,6,11,7,5,4,2,1,3,6,11,7,5,4,2,1,11,11,11,7,13,14,14,3,11,7,1,0,6,5,4,2,1,9,10,3,6,11,7,5,4,2,1,15,11,11,11,11,9,10,3,6,11,7,5,4,2,1,16,12,8,7,1,11,0,17,17,16,18,11,7,19,15,15,9,20,18,10,9,16,12,21,18,8,22,23,5,1,3,6,11,7,5,4,2,1,2,9,10,3,6,11,7,5,4,2,1,9,10,3,6,11,7,5,4,2,1,9,10,3,6,11,7,5,4,2,1,10,10,9,10,3,6,11,7,5,4,2,1,0,0,24,24,24,0,25,24,24,24,24,24,24,24,24,24,24,24,26,27,28,28,0,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,0,28,28,28,0,0,28,28,28,28,29,30,29,30],"f":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["uplo",4]],["i8",0]],[[["transpose",4]],["i8",0]],[[["normtype",4]],["i8",0]],[[["eigenvectorflag",4]],["i8",0]],[[["matrixlayout",4],["uplo",4]],["result",6,[["pivot",6]]]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["matrixlayout",4],["uplo",4]],["result",6]],[[["uvtflag",4]],["uvtflag",4]],[[["diag",4]],["diag",4]],[[["tridiagonal",3,[["",26,[["clone",8],["scalar",8]]]]]],["tridiagonal",3,[["",26,[["clone",8],["scalar",8]]]]]],[[["lufactorizedtridiagonal",3,[["",26,[["clone",8],["scalar",8]]]]]],["lufactorizedtridiagonal",3,[["",26,[["clone",8],["scalar",8]]]]]],[[["uplo",4]],["uplo",4]],[[["transpose",4]],["transpose",4]],[[["normtype",4]],["normtype",4]],[[["eigenvectorflag",4]],["eigenvectorflag",4]],[[["",0],["",0]]],[[["",0],["",0]]],[[["",0],["",0]]],[[["",0],["",0]]],[[["",0],["",0]]],[[["",0],["",0]]],[[["",0],["",0]]],[[["",0],["",0]]],null,null,null,null,[[["bool",0],["matrixlayout",4]],["result",6]],[[["bool",0],["matrixlayout",4],["uplo",4]],["result",6,[["vec",3]]]],[[["bool",0],["matrixlayout",4],["uplo",4]],["result",6,[["vec",3]]]],[[["uvtflag",4],["uvtflag",4]],["bool",0]],[[["tridiagonal",3,[["",26,[["partialeq",8],["scalar",8]]]]],["tridiagonal",3]],["bool",0]],[[["lufactorizedtridiagonal",3,[["",26,[["partialeq",8],["scalar",8]]]]],["lufactorizedtridiagonal",3]],["bool",0]],[[["eigenvectorflag",4],["eigenvectorflag",4]],["bool",0]],null,[[["diag",4],["formatter",3]],["result",6]],[[["uplo",4],["formatter",3]],["result",6]],[[["transpose",4],["formatter",3]],["result",6]],[[["normtype",4],["formatter",3]],["result",6]],[[["eigenvectorflag",4],["formatter",3]],["result",6]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["matrixlayout",4]],["result",6,[["vec",3]]]],[[["tridiagonal",3,[["scalar",8]]]],["",0]],[[["tridiagonal",3,[["scalar",8]]]],["",0]],[[["tridiagonal",3,[["scalar",8]]]],["",0]],[[["tridiagonal",3,[["scalar",8]]]],["",0]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["matrixlayout",4],["pivot",6]],["result",6]],[[["matrixlayout",4],["uplo",4]],["result",6]],[[["matrixlayout",4],["uplo",4],["pivot",6]],["result",6]],null,[[["eigenvectorflag",4]],["bool",0]],null,null,[[["matrixlayout",4]],["result",6,[["leastsquaresoutput",3]]]],[[["matrixlayout",4],["matrixlayout",4]],["result",6,[["leastsquaresoutput",3]]]],[[["matrixlayout",4]],["result",6,[["pivot",6]]]],[[["tridiagonal",3]],["result",6,[["lufactorizedtridiagonal",3]]]],[[["tridiagonal",3,[["",26,[["partialeq",8],["scalar",8]]]]],["tridiagonal",3]],["bool",0]],[[["lufactorizedtridiagonal",3,[["",26,[["partialeq",8],["scalar",8]]]]],["lufactorizedtridiagonal",3]],["bool",0]],[[["normtype",4],["matrixlayout",4]]],[[["matrixlayout",4]],["result",6]],[[["matrixlayout",4]],["result",6,[["vec",3]]]],null,[[["matrixlayout",4]],["result",6]],[[["lufactorizedtridiagonal",3]],["result",6]],null,null,[[["matrixlayout",4],["transpose",4],["pivot",6]],["result",6]],[[["matrixlayout",4],["uplo",4]],["result",6]],[[["matrixlayout",4],["matrixlayout",4],["uplo",4],["diag",4]],["result",6]],[[["lufactorizedtridiagonal",3],["matrixlayout",4],["transpose",4]],["result",6]],[[["matrixlayout",4],["uplo",4],["pivot",6]],["result",6]],[[["matrixlayout",4],["bool",0],["bool",0]],["result",6,[["svdoutput",3]]]],[[["matrixlayout",4],["uvtflag",4]],["result",6,[["svdoutput",3]]]],[[["uplo",4]],["uplo",4]],[[["eigenvectorflag",4],["fnonce",8]],["option",4]],[[["",0]]],[[["",0]]],[[["",0]]],[[["",0]]],[[["",0]]],[[["",0]]],[[["",0]]],[[["",0]]],[[["normtype",4]],["normtype",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,[[],["result",6]],[[["",0]],["",0]],[[["",0]],["",0]],[[["error",4],["formatter",3]],["result",6]],[[["error",4],["formatter",3]],["result",6]],[[]],[[]],[[["",0]],["string",3]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["matrixlayout",4]],["matrixlayout",4]],[[["",0],["",0]]],[[["matrixlayout",4],["matrixlayout",4]],["bool",0]],[[["matrixlayout",4],["formatter",3]],["result",6]],[[]],[[]],[[["matrixlayout",4]],["bool",0]],[[["matrixlayout",4]],["i32",0]],[[["matrixlayout",4]],["i32",0]],[[["matrixlayout",4],["matrixlayout",4]],["bool",0]],[[["matrixlayout",4],["i32",0],["i32",0]],["matrixlayout",4]],[[["matrixlayout",4],["matrixlayout",4]],["bool",0]],[[["matrixlayout",4]]],[[["matrixlayout",4]]],[[["matrixlayout",4]],["matrixlayout",4]],[[["",0]]],[[["matrixlayout",4]],["matrixlayout",4]],[[["matrixlayout",4]]],[[["matrixlayout",4]],["matrixlayout",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null],"p":[[4,"EigenVectorFlag"],[4,"NormType"],[4,"UVTFlag"],[4,"Transpose"],[4,"UPLO"],[4,"Diag"],[3,"LUFactorizedTridiagonal"],[8,"Solveh_"],[3,"LeastSquaresOutput"],[3,"SVDOutput"],[3,"Tridiagonal"],[8,"Cholesky_"],[8,"Eig_"],[8,"Eigh_"],[8,"QR_"],[8,"Solve_"],[8,"LeastSquaresSvdDivideConquer_"],[8,"Tridiagonal_"],[8,"OperatorNorm_"],[8,"Rcond_"],[8,"Triangular_"],[8,"SVD_"],[8,"SVDDC_"],[4,"Error"],[8,"AsLapackResult"],[13,"LapackInvalidValue"],[13,"LapackComputationalFailure"],[4,"MatrixLayout"],[13,"F"],[13,"C"]]},\ +"ndarray_linalg":{"doc":"The ndarray-linalg crate provides linear algebra …","t":[13,13,3,4,3,0,14,14,14,14,14,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,8,3,8,8,8,8,8,8,8,8,13,16,16,16,16,16,16,8,4,13,11,11,10,10,10,10,11,10,11,12,10,10,11,11,11,11,10,11,10,11,10,11,10,11,11,10,11,11,11,11,11,12,11,5,5,5,5,5,5,5,8,3,8,11,10,11,11,11,11,10,11,11,11,11,8,16,16,8,16,10,10,16,16,16,16,16,16,8,8,8,16,8,8,8,16,16,8,8,10,10,10,10,10,10,10,10,13,13,4,13,13,13,6,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,5,5,5,5,5,5,5,5,5,16,8,10,13,4,2,6,13,16,13,6,2,2,8,6,6,13,4,13,10,0,2,2,11,11,11,11,11,11,10,11,10,10,10,11,11,11,11,10,0,2,11,11,11,11,11,11,10,0,2,5,11,11,10,11,11,11,11,11,11,11,11,12,12,3,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,3,11,11,11,11,5,11,11,11,11,11,11,11,11,11,11,5,11,11,11,5,11,11,11,11,11,11,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,11,11,11,11,11,11,8,8,13,16,13,4,10,10,11,11,11,11,10,11,11,11,11,11,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,12,12,12,12,3,8,8,8,11,11,11,11,11,11,11,10,10,10,12,12,12,12,11,11,11,11,11,13,13,4,13,13,13,3,4,3,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,13,8,4,16,13,11,11,11,11,11,10,10,10,5,11,11,11,11,16,8,11,11,11,11,11,11,13,13,4,13,8,16,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,13,16,16,16,8,8,8,8,8,16,16,16,16,16,4,13,10,10,10,10,10,8,8,8,8,13,8,8,3,13,16,16,6,8,8,8,4,13,11,11,11,11,11,11,11,11,11,11,11,10,10,11,11,11,11,11,10,11,10,11,10,11,10,11,10,11,10,11,11,11,10,11,11,10,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,3,8,8,16,16,8,8,8,8,13,16,16,6,8,4,13,12,11,11,11,11,11,11,11,10,11,10,11,10,10,11,11,11,11,11,10,11,10,11,12,10,11,10,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,8,8,8,16,16,16,16,16,16,16,16,16,10,10,10,13,13,8,8,8,16,16,16,13,16,16,16,4,16,16,16,11,11,11,11,11,11,11,10,10,10,11,11,11,11,11,16,8,10,4,8,13,8,8,8,13,11,11,11,11,11,11,11,10,10,10,10,11,11,11,11,11,8,8,8,8,3,8,8,8,8,3,12,11,11,11,11,11,11,11,11,12,10,11,12,12,12,11,11,10,10,11,10,11,11,11,11,11,11,11,11,11,12,12,11,11,11,10,11,10,11,10,11,11,11,11,10,11,11,10,11,11,11,11,10,11,11,11,11,10,11,11,10,11,11,11,11,10,11,11,11,11,10,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,16,8,16,8,10,10,10,10,10,10,10,10,10,10,6,6,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10],"n":["Largest","Smallest","TruncatedEig","TruncatedOrder","TruncatedSvd","assert","assert_aclose","assert_close_l1","assert_close_l2","assert_close_max","assert_rclose","cholesky","constraints","convert","diagonal","eig","eigh","error","generate","inner","krylov","layout","least_squares","lobpcg","norm","operator","opnorm","qr","solve","solveh","svd","svddc","trace","triangular","tridiagonal","types","aclose","close_l1","close_l2","close_max","rclose","Cholesky","CholeskyFactorized","CholeskyInplace","CholeskyInto","DeterminantC","DeterminantCInto","FactorizeC","FactorizeCInto","InverseC","InverseCInto","Lower","Output","Output","Output","Output","Output","Output","SolveC","UPLO","Upper","borrow","borrow_mut","cholesky","cholesky_inplace","cholesky_into","detc","detc","detc_into","detc_into","factor","factorizec","factorizec_into","from","into","into_lower","into_upper","invc","invc","invc_into","invc_into","ln_detc","ln_detc","ln_detc_into","ln_detc_into","solvec","solvec_inplace","solvec_inplace","solvec_into","try_from","try_into","type_id","uplo","vzip","flatten","generalize","into_col","into_matrix","into_row","replicate","transpose_data","AsDiagonal","Diagonal","IntoDiagonal","apply_mut","as_diagonal","borrow","borrow_mut","from","into","into_diagonal","try_from","try_into","type_id","vzip","Eig","EigVal","EigVal","EigVals","EigVec","eig","eigvals","EigVal","EigVal","EigVal","EigVal","EigVal","EigVal","EigValsh","EigValshInplace","EigValshInto","EigVec","Eigh","EighInplace","EighInto","Output","Output","SymmetricSqrt","SymmetricSqrtInto","eigh","eigh_inplace","eigh_into","eigvalsh","eigvalsh_inplace","eigvalsh_into","ssqrt","ssqrt_into","InvalidStride","Lapack","LinalgError","MemoryNotCont","NotSquare","NotStandardShape","Result","Shape","borrow","borrow_mut","fmt","fmt","from","from","from","into","source","to_string","try_from","try_into","type_id","vzip","0","0","cols","cols","obj","rows","rows","s0","s1","conjugate","from_diag","hstack","random","random_hermite","random_hpd","random_regular","random_unitary","vstack","Elem","InnerProduct","inner","Added","AppendResult","Arnoldi","Coefficients","Dependent","Elem","Full","H","Householder","MGS","Orthogonalizer","Q","R","Skip","Strategy","Terminate","append","arnoldi","arnoldi_householder","arnoldi_mgs","borrow","borrow","borrow_mut","borrow_mut","clone","clone_into","coeff","coeff","decompose","dim","div_append","eq","fmt","from","from","get_q","householder","householder","into","into","into_coeff","is_dependent","is_empty","is_full","len","mgs","mgs","qr","residual_norm","to_owned","tolerance","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","0","0","Arnoldi","arnoldi_householder","arnoldi_mgs","borrow","borrow_mut","complete","dim","from","into","into_iter","new","next","try_from","try_into","type_id","vzip","Householder","append","backward_reflection","borrow","borrow_mut","calc_reflector","clone","clone_into","coeff","decompose","dim","div_append","fmt","forward_reflection","from","get_q","householder","into","len","new","reflect","to_owned","tolerance","try_from","try_into","type_id","vzip","MGS","append","borrow","borrow_mut","clone","clone_into","coeff","decompose","dim","div_append","fmt","from","get_q","into","len","mgs","new","to_owned","tolerance","try_from","try_into","type_id","vzip","AllocatedArray","AllocatedArrayMut","C","Elem","F","MatrixLayout","as_allocated","as_allocated_mut","borrow","borrow_mut","clone","clone_into","ensure_square","eq","fmt","from","into","is_empty","layout","lda","len","ne","resized","same_order","size","square_layout","t","to_owned","toggle_order","try_from","try_into","type_id","vzip","col","lda","lda","row","LeastSquaresResult","LeastSquaresSvd","LeastSquaresSvdInPlace","LeastSquaresSvdInto","borrow","borrow_mut","clone","clone_into","fmt","from","into","least_squares","least_squares_in_place","least_squares_into","rank","residual_sum_of_squares","singular_values","solution","to_owned","try_from","try_into","type_id","vzip","Err","Largest","LobpcgResult","NoResult","Ok","Smallest","TruncatedEig","TruncatedOrder","TruncatedSvd","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","constraints","decompose","decompose","fmt","fmt","from","from","from","from","into","into","into","into","into_iter","lobpcg","maxiter","maxiter","new","new","orthogonal_to","precision","precision","precondition_with","to_owned","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","0","0","0","1","1","2","2","3","Column","Norm","NormalizeAxis","Output","Row","borrow","borrow_mut","from","into","norm","norm_l1","norm_l2","norm_max","normalize","try_from","try_into","type_id","vzip","Elem","LinearOperator","apply","apply2","apply2_into","apply2_mut","apply_into","apply_mut","Frobenius","Infinity","NormType","One","OperationNorm","Output","as_ptr","borrow","borrow_mut","clone","clone_into","fmt","from","into","opnorm","opnorm_fro","opnorm_inf","opnorm_one","to_owned","transpose","try_from","try_into","type_id","vzip","Lower","Q","Q","Q","QR","QRInto","QRSquare","QRSquareInplace","QRSquareInto","R","R","R","R","R","UPLO","Upper","qr","qr_into","qr_square","qr_square_inplace","qr_square_into","Determinant","DeterminantInto","Factorize","FactorizeInto","Hermite","Inverse","InverseInto","LUFactorized","No","Output","Output","Pivot","ReciprocalConditionNum","ReciprocalConditionNumInto","Solve","Transpose","Transpose","as_ptr","borrow","borrow","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","det","det_into","factorize","factorize_into","fmt","from","from","into","into","inv","inv","inv_into","inv_into","rcond","rcond","rcond_into","rcond_into","sln_det","sln_det","sln_det_into","sln_det_into","solve","solve_h","solve_h_inplace","solve_h_inplace","solve_h_into","solve_inplace","solve_inplace","solve_into","solve_t","solve_t_inplace","solve_t_inplace","solve_t_into","to_owned","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","BKFactorized","DeterminantH","DeterminantHInto","Elem","Elem","FactorizeH","FactorizeHInto","InverseH","InverseHInto","Lower","Output","Output","Pivot","SolveH","UPLO","Upper","a","as_ptr","borrow","borrow","borrow_mut","borrow_mut","clone","clone_into","deth","deth","deth_into","deth_into","factorizeh","factorizeh_into","fmt","from","from","into","into","invh","invh","invh_into","invh_into","ipiv","sln_deth","sln_deth","sln_deth_into","sln_deth_into","solveh","solveh_inplace","solveh_inplace","solveh_into","t","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","SVD","SVDInplace","SVDInto","Sigma","Sigma","Sigma","U","U","U","VT","VT","VT","svd","svd_inplace","svd_into","Full","None","SVDDC","SVDDCInplace","SVDDCInto","Sigma","Sigma","Sigma","Some","U","U","U","UVTFlag","VT","VT","VT","borrow","borrow_mut","clone","clone_into","eq","from","into","svddc","svddc_inplace","svddc_into","to_owned","try_from","try_into","type_id","vzip","Output","Trace","trace","Diag","IntoTriangular","NonUnit","SolveTriangular","SolveTriangularInplace","SolveTriangularInto","Unit","borrow","borrow_mut","clone","clone_into","fmt","from","into","into_triangular","solve_triangular","solve_triangular_inplace","solve_triangular_into","to_owned","try_from","try_into","type_id","vzip","DeterminantTridiagonal","ExtractTridiagonal","FactorizeTridiagonal","FactorizeTridiagonalInto","LUFactorizedTridiagonal","ReciprocalConditionNumTridiagonal","ReciprocalConditionNumTridiagonalInto","SolveTridiagonal","SolveTridiagonalInplace","Tridiagonal","a","borrow","borrow","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","d","det_tridiagonal","det_tridiagonal","dl","du","du2","eq","eq","extract_tridiagonal","factorize_tridiagonal","factorize_tridiagonal","factorize_tridiagonal_into","factorize_tridiagonal_into","from","from","index","index","index_mut","index_mut","into","into","ipiv","l","ne","ne","opnorm","rcond_tridiagonal","rcond_tridiagonal","rcond_tridiagonal_into","rcond_tridiagonal_into","solve_h_tridiagonal","solve_h_tridiagonal","solve_h_tridiagonal","solve_h_tridiagonal","solve_h_tridiagonal","solve_h_tridiagonal_inplace","solve_h_tridiagonal_inplace","solve_h_tridiagonal_inplace","solve_h_tridiagonal_into","solve_h_tridiagonal_into","solve_h_tridiagonal_into","solve_h_tridiagonal_into","solve_h_tridiagonal_into","solve_t_tridiagonal","solve_t_tridiagonal","solve_t_tridiagonal","solve_t_tridiagonal","solve_t_tridiagonal","solve_t_tridiagonal_inplace","solve_t_tridiagonal_inplace","solve_t_tridiagonal_inplace","solve_t_tridiagonal_into","solve_t_tridiagonal_into","solve_t_tridiagonal_into","solve_t_tridiagonal_into","solve_t_tridiagonal_into","solve_tridiagonal","solve_tridiagonal","solve_tridiagonal","solve_tridiagonal","solve_tridiagonal","solve_tridiagonal_inplace","solve_tridiagonal_inplace","solve_tridiagonal_inplace","solve_tridiagonal_into","solve_tridiagonal_into","solve_tridiagonal_into","solve_tridiagonal_into","solve_tridiagonal_into","to_owned","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","Complex","Lapack","Real","Scalar","abs","acos","acosh","add_complex","add_real","as_c","asin","asinh","atan","atanh","c32","c64","complex","conj","cos","cosh","div_complex","div_real","exp","from_real","im","ln","mul_complex","mul_real","pow","powc","powf","powi","rand","re","real","sin","sinh","sqrt","square","sub_complex","sub_real","tan","tanh"],"q":["ndarray_linalg","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::assert","","","","","ndarray_linalg::cholesky","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::convert","","","","","","","ndarray_linalg::diagonal","","","","","","","","","","","","","","ndarray_linalg::eig","","","","","","","ndarray_linalg::eigh","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::error","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::error::LinalgError","","","","","","","","","ndarray_linalg::generate","","","","","","","","","ndarray_linalg::inner","","","ndarray_linalg::krylov","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::krylov::AppendResult","","ndarray_linalg::krylov::arnoldi","","","","","","","","","","","","","","","","ndarray_linalg::krylov::householder","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::krylov::mgs","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::layout","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::layout::MatrixLayout","","","","ndarray_linalg::least_squares","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::lobpcg","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::lobpcg::LobpcgResult","","","","","","","","ndarray_linalg::norm","","","","","","","","","","","","","","","","","","ndarray_linalg::operator","","","","","","","","ndarray_linalg::opnorm","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::qr","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::solve","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::solveh","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::svd","","","","","","","","","","","","","","","ndarray_linalg::svddc","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::trace","","","ndarray_linalg::triangular","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::tridiagonal","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","ndarray_linalg::types","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["","","Truncated eigenproblem solver","Find largest or smallest eigenvalues","Truncated singular value decomposition","Assertions for array","","","","","","Cholesky decomposition of Hermitian (or real symmetric) …","","utilities for convert array","Vector as a Diagonal matrix","Eigenvalue decomposition for non-symmetric square matrices","Eigendecomposition for Hermitian matrices.","Define Errors","Generator functions for matrices","","Krylov subspace methods","Convert ndarray into LAPACK-compatible matrix format","Least Squares","","Norm of vectors","Linear operator algebra","Operator norm","QR decomposition","Solve systems of linear equations and invert matrices","Solve Hermitian (or real symmetric) linear problems and …","Singular-value decomposition (SVD)","Singular-value decomposition (SVD) by divide-and-conquer …","Trace calculation","Methods for triangular matrices","Vectors as a Tridiagonal matrix & Methods for tridiagonal …","Basic types and their methods for linear algebra","check two values are close in terms of the absolute …","check two arrays are close in L1 norm","check two arrays are close in L2 norm","check two arrays are close in maximum norm","check two values are close in terms of the relative …","Cholesky decomposition of Hermitian (or real symmetric) …","Cholesky decomposition of Hermitian (or real symmetric) …","Cholesky decomposition of Hermitian (or real symmetric) …","Cholesky decomposition of Hermitian (or real symmetric) …","Determinant of Hermitian (or real symmetric) positive …","Determinant of Hermitian (or real symmetric) positive …","Cholesky decomposition of Hermitian (or real symmetric) …","Cholesky decomposition of Hermitian (or real symmetric) …","Inverse of Hermitian (or real symmetric) positive definite …","Inverse of Hermitian (or real symmetric) positive definite …","","","","","","","","Solve systems of linear equations with Hermitian (or real …","Upper/Lower specification for seveal usages","","","","Computes the Cholesky decomposition of the Hermitian (or …","Computes the Cholesky decomposition of the Hermitian (or …","Computes the Cholesky decomposition of the Hermitian (or …","Computes the determinant of the Hermitian (or real …","","Computes the determinant of the Hermitian (or real …","","L from the decomposition A = L * L^H or U from the …","Computes the Cholesky decomposition of the Hermitian (or …","Computes the Cholesky decomposition of the Hermitian (or …","Returns the argument unchanged.","Calls U::from(self).","Returns L from the Cholesky decomposition A = L * L^H.","Returns U from the Cholesky decomposition A = U^H * U.","Computes the inverse of the Hermitian (or real symmetric) …","","Computes the inverse of the Hermitian (or real symmetric) …","","Computes the natural log of the determinant of the …","","Computes the natural log of the determinant of the …","","Solves a system of linear equations A * x = b with …","Solves a system of linear equations A * x = b with …","","Solves a system of linear equations A * x = b with …","","","","If this is UPLO::Lower, then self.factor is L. If this is …","","","","","","","","","","Vector as a Diagonal matrix","","","","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","Eigenvalue decomposition of general matrix reference","EigVec is the right eivenvector","","Calculate eigenvalues without eigenvectors","","Calculate eigenvalues with the right eigenvector","","","","","","","","Calculate eigenvalues without eigenvectors","Calculate eigenvalues without eigenvectors","Calculate eigenvalues without eigenvectors","","Eigenvalue decomposition of Hermite matrix reference","Eigenvalue decomposition of mutable reference of Hermite …","Eigenvalue decomposition of Hermite matrix","","","Calculate symmetric square-root matrix using eigh","Calculate symmetric square-root matrix using eigh","","","","","","","","","Strides of the array is not supported","LAPACK subroutine returns non-zero code","Master Error type of this crate","Memory is not aligned continously","Matrix is not square","Obj cannot be made from a (rows, cols) matrix","","Strides of the array is not supported","","","","","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","","","","","","","","","","","Hermite conjugate matrix","construct matrix from diag","stack vectors into matrix horizontally","Generate random array","Random Hermite matrix","Random Hermite Positive-definite matrix","Generate random regular matrix","Generate random unitary matrix using QR decomposition","stack vectors into matrix vertically","","Inner Product","Inner product `(self.conjugate, rhs)","","","","Array type for coefficients to the current basis","","","Orthogonalize dependent vector without adding to Q, i.e. R …","H-matrix","","","Trait for creating orthogonal basis from iterator of arrays","Q-matrix","R-matrix","Skip dependent vector","Strategy for linearly dependent vectors appearing in …","Terminate iteration if dependent vector comes","Add new vector if the residual is larger than relative …","Arnoldi iteration","","","","","","","","","Calculate the coefficient to the current basis basis","","Decompose given vector into the span of current basis and …","Dimension of input array","Add new vector if the residual is larger than relative …","","","Returns the argument unchanged.","Returns the argument unchanged.","Get Q-matrix of generated basis","Householder reflection","","Calls U::from(self).","Calls U::from(self).","","","","check if the basis spans entire space","Number of cached basis","Modified Gram-Schmit orthogonalizer","","Online QR decomposition using arbitrary orthogonalizer","","","","","","","","","","","","","","Execute Arnoldi iteration as Rust iterator","Utility to execute Arnoldi iteration with Householder …","Utility to execute Arnoldi iteration with modified …","","","Iterate until convergent","Dimension of Krylov subspace","Returns the argument unchanged.","Calls U::from(self).","","Create an Arnoldi iterator from any linear operator a","","","","","","Iterative orthogonalizer using Householder reflection","","Take backward reflection P = P_1 ... P_l","","","Calc a reflactor w from a vector x","","","","","","","","Take forward reflection P = P_l ... P_1","Returns the argument unchanged.","","Online QR decomposition using Householder reflection","Calls U::from(self).","","Create a new orthogonalizer","Take a reflection P = I - 2ww^T","","","","","","","Iterative orthogonalizer using modified Gram-Schmit …","","","","","","","","","","","Returns the argument unchanged.","","Calls U::from(self).","","Online QR decomposition using modified Gram-Schmit …","Create an empty orthogonalizer","","","","","","","","","","","","","","","","","","","Returns Ok iff the matrix is square (without computing the …","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","","","","","Transpose without changing memory representation","","","","","","","","","","","Result of a LeastSquares computation","Solve least squares for immutable references","Solve least squares for mutable references, overwriting …","Solve least squares for owned matrices","","","","","","Returns the argument unchanged.","Calls U::from(self).","Solve a least squares problem of the form Ax = rhs by …","Solve a least squares problem of the form Ax = rhs by …","Solve a least squares problem of the form Ax = rhs by …","The rank of the matrix A in Ax = b","If n < m and rank(A) == n, the sum of squares If b is a (m …","The singular values of the matrix A in Ax = b","The solution vector or matrix x which is the best solution …","","","","","","","","The result of the eigensolver","","","","Truncated eigenproblem solver","Find largest or smallest eigenvalues","Truncated singular value decomposition","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","Eigenvalue solver for large symmetric positive definite …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Define norm as a metric linear space (not as a matrix)","","","","","","Returns the argument unchanged.","Calls U::from(self).","rename of norm_l2","L-1 norm","L-2 norm","maximum norm","normalize in L2 norm","","","","","","Abstracted linear operator as an action to vector (…","Apply operator out-place","Apply operator to matrix out-place","Apply operator to matrix with move","Apply operator to matrix in-place","Apply operator with move","Apply operator in-place","","","","","Operator norm using *lange LAPACK routines","the value of norm","To use Fortran LAPACK API in lapack-sys crate","","","","","","Returns the argument unchanged.","Calls U::from(self).","","the Frobenius norm of a matrix (square root of sum of …","the infinity norm of a matrix (maximum row sum)","the one norm of a matrix (maximum column sum)","","","","","","","","","","","QR decomposition for matrix reference","QR decomposition","QR decomposition for square matrix reference","QR decomposition for mutable reference of square matrix","QR decomposition for square matrix","","","","","","Upper/Lower specification for seveal usages","","","","","","","An interface for calculating determinants of matrix refs.","An interface for calculating determinants of matrices.","An interface for computing LU factorizations of matrix …","An interface for computing LU factorizations of matrices.","","An interface for inverting matrix refs.","An interface for inverting matrices.","Represents the LU factorization of a matrix A as A = P*L*U.","","","","","An interface for estimating the reciprocal condition …","An interface for estimating the reciprocal condition …","An interface for solving systems of linear equations.","","","To use Fortran LAPACK API in lapack-sys crate","","","","","","","","","Computes the determinant of the matrix.","Computes the determinant of the matrix.","Computes the LU factorization A = P*L*U, where P is a …","Computes the LU factorization A = P*L*U, where P is a …","","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Computes the inverse of the matrix.","","Computes the inverse of the matrix.","","Estimates the reciprocal of the condition number of the …","","Estimates the reciprocal of the condition number of the …","","Computes the (sign, natural_log) of the determinant of the …","","Computes the (sign, natural_log) of the determinant of the …","","Solves a system of linear equations A * x = b where A is …","Solves a system of linear equations A^H * x = b where A is …","Solves a system of linear equations A^H * x = b where A is …","","Solves a system of linear equations A^H * x = b where A is …","Solves a system of linear equations A * x = b where A is …","","Solves a system of linear equations A * x = b where A is …","Solves a system of linear equations A^T * x = b where A is …","Solves a system of linear equations A^T * x = b where A is …","","Solves a system of linear equations A^T * x = b where A is …","","","","","","","","","","","Represents the Bunch–Kaufman factorization of a …","An interface for calculating determinants of Hermitian (or …","An interface for calculating determinants of Hermitian (or …","The element type of the matrix.","The element type of the matrix.","An interface for computing the Bunch–Kaufman …","An interface for computing the Bunch–Kaufman …","An interface for inverting Hermitian (or real symmetric) …","An interface for inverting Hermitian (or real symmetric) …","","","","","An interface for solving systems of Hermitian (or real …","Upper/Lower specification for seveal usages","","","To use Fortran LAPACK API in lapack-sys crate","","","","","","","Computes the determinant of the Hermitian (or real …","Computes the determinant of the factorized Hermitian (or …","Computes the determinant of the Hermitian (or real …","Computes the determinant of the factorized Hermitian (or …","Computes the Bunch–Kaufman factorization of a Hermitian …","Computes the Bunch–Kaufman factorization of a Hermitian …","","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Computes the inverse of the Hermitian (or real symmetric) …","","Computes the inverse of the Hermitian (or real symmetric) …","","","Computes the (sign, natural_log) of the determinant of the …","Computes the (sign, natural_log) of the determinant of the …","Computes the (sign, natural_log) of the determinant of the …","Computes the (sign, natural_log) of the determinant of the …","Solves a system of linear equations A * x = b with …","Solves a system of linear equations A * x = b with …","","Solves a system of linear equations A * x = b with …","","","","","","","","","","","singular-value decomposition of matrix reference","singular-value decomposition for mutable reference of …","singular-value decomposition","","","","","","","","","","","","","All m columns of U and all n rows of Vᵀ.","No columns of U or rows of Vᵀ.","Singular-value decomposition of matrix (copying) by …","Singular-value decomposition of matrix reference by …","Singular-value decomposition of matrix by …","","","","The first min(m,n) columns of U and the first min(m,n) …","","","","Specifies how many of the columns of U and rows of Vᵀ …","","","","","","","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","","","","","","","","","","solve a triangular system with upper triangular matrix","solve a triangular system with upper triangular matrix","solve a triangular system with upper triangular matrix","","","","","","","Returns the argument unchanged.","Calls U::from(self).","","","","","","","","","","An interface for calculating determinants of tridiagonal …","An interface for making a Tridiagonal struct.","An interface for computing LU factorizations of …","An interface for computing LU factorizations of …","Represents the LU factorization of a tridiagonal matrix A …","An interface for estimating the reciprocal condition …","An interface for estimating the reciprocal condition …","","","Represents a tridiagonal matrix as 3 one-dimensional …","A tridiagonal matrix which consists of","","","","","","","","","(n) diagonal elements of matrix.","Computes the determinant of the matrix. Unlike .det() of …","","(n-1) sub-diagonal elements of matrix.","(n-1) super-diagonal elements of matrix.","(n-2) elements of the second super-diagonal of U.","","","Extract tridiagonal elements and layout of the raw matrix.","Computes the LU factorization A = P*L*U, where P is a …","","Computes the LU factorization A = P*L*U, where P is a …","","Returns the argument unchanged.","Returns the argument unchanged.","","","","","Calls U::from(self).","Calls U::from(self).","The pivot indices that define the permutation matrix P.","layout of raw matrix","","","","Estimates the reciprocal of the condition number of the …","","Estimates the reciprocal of the condition number of the …","","Solves a system of linear equations A^H * x = b with …","","","","","Solves a system of linear equations A^H * x = b tridiagonal","","","Solves a system of linear equations A^H * x = b with …","","","","","Solves a system of linear equations A^T * x = b with …","","","","","Solves a system of linear equations A^T * x = b tridiagonal","","","Solves a system of linear equations A^T * x = b with …","","","","","Solves a system of linear equations A * x = b with …","","","","","Solves a system of linear equations A * x = b tridiagonal …","","","Solves a system of linear equations A * x = b with …","","","","","","","","","","","","","","","","Trait for primitive types which implements LAPACK …","","","Absolute value","","","","","As a complex number","","","","","","","Create a new complex number","Complex conjugate","","","","","","","Imaginary part","","","","","","","","Generate an random number from …","Real part","Create a new real number","","","","Sqaure of absolute value","","","",""],"i":[1,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,5,6,7,8,9,0,0,3,10,10,4,11,5,8,10,9,10,10,12,13,10,10,10,10,6,10,7,10,8,10,9,10,14,14,10,14,10,10,10,10,10,0,0,0,0,0,0,0,0,0,0,15,16,15,15,15,15,17,15,15,15,15,0,18,19,0,18,18,19,20,21,22,23,24,25,0,0,0,20,0,0,0,26,27,0,0,20,21,22,23,25,24,26,27,28,28,0,28,28,28,0,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,30,31,32,32,31,32,33,33,0,0,0,0,0,0,0,0,0,34,0,34,35,0,0,0,35,36,37,0,0,0,0,0,0,37,0,37,36,0,0,0,35,37,35,37,37,37,36,35,36,36,36,37,37,35,37,36,0,0,35,37,35,35,36,36,36,0,0,0,35,37,36,35,37,35,37,35,37,35,37,38,39,0,0,0,40,40,40,40,40,40,40,40,40,40,40,40,40,0,41,41,41,41,0,41,41,41,41,41,41,41,41,41,41,0,41,41,41,0,41,41,41,41,41,41,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,42,42,42,42,42,42,42,0,0,43,44,43,0,44,45,43,43,43,43,44,43,43,43,43,43,44,43,43,43,43,43,43,44,43,43,43,43,43,43,43,46,47,46,47,0,0,0,0,48,48,48,48,48,48,48,49,50,51,48,48,48,48,48,48,48,48,48,52,1,0,52,52,1,0,0,0,2,53,1,52,2,53,1,52,1,1,2,2,53,1,52,2,53,1,52,2,53,1,52,2,0,2,53,2,53,2,2,53,2,1,2,53,1,52,2,53,1,52,2,53,1,52,2,53,1,52,54,55,56,54,55,54,55,55,57,0,0,58,57,57,57,57,57,58,58,58,58,0,57,57,57,57,59,0,59,59,59,59,59,59,60,60,0,60,0,61,60,60,60,60,60,60,60,60,61,61,61,61,60,60,60,60,60,60,3,62,63,64,0,0,0,0,0,62,63,64,65,66,0,3,62,63,64,66,65,0,0,0,0,67,0,0,0,67,68,69,0,0,0,0,0,67,67,67,70,67,70,67,70,67,70,71,72,73,74,67,67,70,67,70,68,70,69,70,75,70,76,70,71,70,72,70,77,77,77,70,77,77,70,77,77,77,70,77,67,70,67,70,67,70,67,70,67,70,0,0,0,78,79,0,0,0,0,3,80,81,0,0,0,3,82,3,3,82,3,82,3,3,78,82,79,82,83,84,3,3,82,3,82,80,82,81,82,82,78,82,79,82,85,85,82,85,3,3,3,82,3,82,3,82,3,82,0,0,0,86,87,88,86,87,88,86,87,88,86,88,87,89,89,0,0,0,90,91,92,89,90,91,92,0,90,91,92,89,89,89,89,89,89,89,90,92,91,89,89,89,89,89,93,0,93,0,0,94,0,0,0,94,94,94,94,94,94,94,94,95,96,97,98,94,94,94,94,94,0,0,0,0,0,0,0,0,0,0,99,100,99,100,99,100,99,100,99,100,101,100,100,100,99,100,99,102,103,100,104,100,100,99,100,100,100,100,100,99,99,100,100,99,100,105,99,106,99,107,100,100,99,99,108,100,99,107,100,100,99,99,107,100,100,99,99,108,100,99,107,100,100,99,99,107,100,100,99,99,108,100,99,107,100,100,99,99,100,99,100,99,100,99,100,99,100,99,109,0,109,0,109,109,109,109,109,109,109,109,109,109,0,0,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109],"f":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["scalar",8],["scalar",8]]],[[["arraybase",3],["arraybase",3]]],[[["arraybase",3],["arraybase",3]]],[[["arraybase",3],["arraybase",3]]],[[["scalar",8],["scalar",8]]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["",0],["uplo",4]],["result",6]],[[["",0],["uplo",4]],["result",6]],[[["uplo",4]],["result",6]],[[["",0]]],[[["choleskyfactorized",3]]],[[]],[[["choleskyfactorized",3]]],null,[[["",0],["uplo",4]],["result",6,[["choleskyfactorized",3]]]],[[["uplo",4]],["result",6,[["choleskyfactorized",3]]]],[[]],[[]],[[["choleskyfactorized",3]],["arraybase",3,[["ix2",6]]]],[[["choleskyfactorized",3]],["arraybase",3,[["ix2",6]]]],[[["",0]],["result",6]],[[["choleskyfactorized",3]],["result",6]],[[],["result",6]],[[["choleskyfactorized",3]],["result",6]],[[["",0]]],[[["choleskyfactorized",3]]],[[]],[[["choleskyfactorized",3]]],[[["",0],["arraybase",3]],["result",6,[["array1",6]]]],[[["",0],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["choleskyfactorized",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],null,[[]],[[["arraybase",3,[["ix2",6]]]],["arraybase",3,[["ix1",6]]]],[[["array",6]],["arraybase",3]],[[["arraybase",3,[["ix1",6]]]],["arraybase",3,[["ix2",6]]]],[[["matrixlayout",4],["vec",3]],["result",6,[["arraybase",3,[["ix2",6]]]]]],[[["arraybase",3,[["ix1",6]]]],["arraybase",3,[["ix2",6]]]],[[["arraybase",3]],["arraybase",3]],[[["arraybase",3]],["result",6,[["arraybase",3]]]],null,null,null,[[["diagonal",3],["arraybase",3]]],[[["",0]],["diagonal",3,[["viewrepr",3]]]],[[["",0]],["",0]],[[["",0]],["",0]],[[]],[[]],[[],["diagonal",3]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null,null,[[["",0]],["result",6]],[[["",0]],["result",6]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["",0],["uplo",4]],["result",6]],[[["",0],["uplo",4]],["result",6]],[[["uplo",4]],["result",6]],[[["",0],["uplo",4]],["result",6]],[[["",0],["uplo",4]],["result",6]],[[["uplo",4]],["result",6]],[[["",0],["uplo",4]],["result",6]],[[["uplo",4]],["result",6]],null,null,null,null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["linalgerror",4],["formatter",3]],["result",6]],[[["linalgerror",4],["formatter",3]],["result",6]],[[["error",4]],["linalgerror",4]],[[["shapeerror",3]],["linalgerror",4]],[[]],[[]],[[["linalgerror",4]],["option",4,[["error",8]]]],[[["",0]],["string",3]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,[[["arraybase",3]],["arraybase",3,[["ix2",6]]]],[[],["array2",6]],[[],["result",6,[["array",6,[["ix2",6]]]]]],[[],["arraybase",3]],[[["usize",0]],["arraybase",3,[["ix2",6]]]],[[["usize",0]],["arraybase",3,[["ix2",6]]]],[[["usize",0]],["array2",6]],[[["usize",0]],["array2",6]],[[],["result",6,[["array",6,[["ix2",6]]]]]],null,null,[[["",0],["arraybase",3]]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["",0],["arraybase",3,[["ix1",6]]]],["appendresult",4]],null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["strategy",4]],["strategy",4]],[[["",0],["",0]]],[[["",0],["arraybase",3,[["ix1",6]]]],["coefficients",6]],[[["appendresult",4,[["scalar",8]]]],["coefficients",6]],[[["",0],["arraybase",3]],["coefficients",6]],[[["",0]],["usize",0]],[[["",0],["arraybase",3]],["appendresult",4]],[[["strategy",4],["strategy",4]],["bool",0]],[[["strategy",4],["formatter",3]],["result",6]],[[]],[[]],[[["",0]],["q",6]],null,null,[[]],[[]],[[["appendresult",4,[["scalar",8]]]],["coefficients",6,[["scalar",8]]]],[[["appendresult",4,[["scalar",8]]]],["bool",0]],[[["",0]],["bool",0]],[[["",0]],["bool",0]],[[["",0]],["usize",0]],null,null,[[["iterator",8],["orthogonalizer",8],["strategy",4]]],[[["appendresult",4,[["scalar",8]]]]],[[["",0]]],[[["",0]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[]],[[]],null,null,null,[[["linearoperator",8],["arraybase",3,[["ix1",6]]]]],[[["linearoperator",8],["arraybase",3,[["ix1",6]]]]],[[["",0]],["",0]],[[["",0]],["",0]],[[["arnoldi",3]]],[[["arnoldi",3]],["usize",0]],[[]],[[]],[[]],[[["arraybase",3,[["ix1",6]]]],["arnoldi",3]],[[["arnoldi",3]],["option",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3,[["ix1",6]]]],["appendresult",4,[["",26,[["scalar",8],["lapack",8]]]]]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3]]],[[["",0]],["",0]],[[["",0]],["",0]],[[["arraybase",3]]],[[["householder",3,[["",26,[["clone",8],["scalar",8]]]]]],["householder",3,[["",26,[["clone",8],["scalar",8]]]]]],[[["",0],["",0]]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3,[["ix1",6]]]],["array1",6,[["",26,[["scalar",8],["lapack",8]]]]]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3]],["array1",6,[["",26,[["scalar",8],["lapack",8]]]]]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]]],["usize",0]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3]],["appendresult",4,[["",26,[["scalar",8],["lapack",8]]]]]],[[["householder",3,[["",26,[["debug",8],["scalar",8]]]]],["formatter",3]],["result",6]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3]]],[[]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]]],["q",6,[["",26,[["scalar",8],["lapack",8]]]]]],[[["iterator",8],["usize",0],["strategy",4]]],[[]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]]],["usize",0]],[[["usize",0]],["householder",3,[["",26,[["scalar",8],["lapack",8]]]]]],[[["arraybase",3],["arraybase",3]]],[[["",0]]],[[["householder",3,[["",26,[["scalar",8],["lapack",8]]]]]]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,[[["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3,[["ix1",6]]]],["appendresult",4,[["",26,[["scalar",8],["lapack",8]]]]]],[[["",0]],["",0]],[[["",0]],["",0]],[[["mgs",3,[["",26,[["clone",8],["scalar",8]]]]]],["mgs",3,[["",26,[["clone",8],["scalar",8]]]]]],[[["",0],["",0]]],[[["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3,[["ix1",6]]]],["array1",6,[["",26,[["scalar",8],["lapack",8]]]]]],[[["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3]],["array1",6,[["",26,[["scalar",8],["lapack",8]]]]]],[[["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]]],["usize",0]],[[["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]],["arraybase",3]],["appendresult",4,[["",26,[["scalar",8],["lapack",8]]]]]],[[["mgs",3,[["",26,[["debug",8],["scalar",8]]]]],["formatter",3]],["result",6]],[[]],[[["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]]],["q",6,[["",26,[["scalar",8],["lapack",8]]]]]],[[]],[[["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]]],["usize",0]],[[["iterator",8],["usize",0],["strategy",4]]],[[["usize",0]],["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]]],[[["",0]]],[[["mgs",3,[["",26,[["scalar",8],["lapack",8]]]]]]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null,null,null,[[["",0]],["result",6]],[[["",0]],["result",6]],[[["",0]],["",0]],[[["",0]],["",0]],[[["matrixlayout",4]],["matrixlayout",4]],[[["",0],["",0]]],[[["",0]],["result",6]],[[["matrixlayout",4],["matrixlayout",4]],["bool",0]],[[["matrixlayout",4],["formatter",3]],["result",4,[["error",3]]]],[[]],[[]],[[["matrixlayout",4]],["bool",0]],[[["",0]],["result",6,[["matrixlayout",4]]]],[[["matrixlayout",4]],["i32",0]],[[["matrixlayout",4]],["i32",0]],[[["matrixlayout",4],["matrixlayout",4]],["bool",0]],[[["matrixlayout",4],["i32",0],["i32",0]],["matrixlayout",4]],[[["matrixlayout",4],["matrixlayout",4]],["bool",0]],[[["matrixlayout",4]]],[[["",0]],["result",6,[["matrixlayout",4]]]],[[["matrixlayout",4]],["matrixlayout",4]],[[["",0]]],[[["matrixlayout",4]],["matrixlayout",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["leastsquaresresult",3,[["",26,[["clone",8],["scalar",8]]],["",26,[["clone",8],["dimension",8]]]]]],["leastsquaresresult",3,[["",26,[["clone",8],["scalar",8]]],["",26,[["clone",8],["dimension",8]]]]]],[[["",0],["",0]]],[[["leastsquaresresult",3,[["",26,[["debug",8],["scalar",8]]],["",26,[["debug",8],["dimension",8]]]]],["formatter",3]],["result",6]],[[]],[[]],[[["",0],["arraybase",3]],["result",6,[["leastsquaresresult",3]]]],[[["",0],["arraybase",3]],["result",6,[["leastsquaresresult",3]]]],[[["arraybase",3]],["result",6,[["leastsquaresresult",3]]]],null,null,null,null,[[["",0]]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["order",4]],["order",4]],[[["",0],["",0]]],null,[[["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["usize",0]],["lobpcgresult",4,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["truncatedsvd",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["usize",0]],["result",6,[["truncatedsvdresult",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]]]],[[["order",4],["formatter",3]],["result",6]],[[["lobpcgresult",4,[["debug",8]]],["formatter",3]],["result",6]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],["truncatedeigiterator",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["fn",8],["array2",6,[["",26,[["float",8],["scalar",8],["lapack",8],["scalaroperand",8],["partialord",8],["default",8]]]]],["fn",8],["option",4,[["array2",6,[["",26,[["float",8],["scalar",8],["lapack",8],["scalaroperand",8],["partialord",8],["default",8]]]]]]],["f32",0],["usize",0],["order",4]],["lobpcgresult",4,[["",26,[["float",8],["scalar",8],["lapack",8],["scalaroperand",8],["partialord",8],["default",8]]]]]],[[["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["usize",0]],["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["truncatedsvd",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["usize",0]],["truncatedsvd",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["array2",6,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["order",4]],["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["array2",6,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["order",4]],["truncatedsvd",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["array2",6,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["f32",0]],["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["truncatedsvd",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["f32",0]],["truncatedsvd",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]],["array2",6,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],["truncatedeig",3,[["",26,[["float",8],["scalar",8],["scalaroperand",8],["lapack",8],["partialord",8],["default",8]]]]]],[[["",0]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[]],[[]],[[["",0]]],[[["",0]]],[[["",0]]],[[["",0]]],[[["arraybase",3,[["ix2",6]]],["normalizeaxis",4]]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,[[["",0],["arraybase",3]],["array1",6]],[[["",0],["arraybase",3]],["array2",6]],[[["",0],["arraybase",3,[["ix2",6]]]],["arraybase",3,[["ix2",6]]]],[[["",0],["arraybase",3]]],[[["",0],["arraybase",3,[["ix1",6]]]],["arraybase",3,[["ix1",6]]]],[[["",0],["arraybase",3]]],null,null,null,null,null,null,[[["normtype",4]],["i8",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["normtype",4]],["normtype",4]],[[["",0],["",0]]],[[["normtype",4],["formatter",3]],["result",4,[["error",3]]]],[[]],[[]],[[["",0],["normtype",4]],["result",6]],[[["",0]],["result",6]],[[["",0]],["result",6]],[[["",0]],["result",6]],[[["",0]]],[[["normtype",4]],["normtype",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["",0]],["result",6]],[[],["result",6]],[[["",0]],["result",6]],[[["",0]],["result",6]],[[],["result",6]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["transpose",4]],["i8",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["transpose",4]],["transpose",4]],[[["lufactorized",3,[["",26,[["clone",8],["data",8],["rawdataclone",8]]]]]],["lufactorized",3,[["",26,[["clone",8],["data",8],["rawdataclone",8]]]]]],[[["",0],["",0]]],[[["",0],["",0]]],[[["",0]],["result",6]],[[],["result",6]],[[["",0]],["result",6,[["lufactorized",3]]]],[[],["result",6,[["lufactorized",3]]]],[[["transpose",4],["formatter",3]],["result",4,[["error",3]]]],[[]],[[]],[[]],[[]],[[["",0]],["result",6]],[[["lufactorized",3]],["result",6,[["array2",6]]]],[[],["result",6]],[[["lufactorized",3]],["result",6,[["arraybase",3,[["ix2",6]]]]]],[[["",0]],["result",6]],[[["lufactorized",3]],["result",6]],[[],["result",6]],[[["lufactorized",3]],["result",6]],[[["",0]],["result",6]],[[["lufactorized",3]],["result",6]],[[],["result",6]],[[["lufactorized",3]],["result",6]],[[["",0],["arraybase",3]],["result",6,[["array1",6]]]],[[["",0],["arraybase",3]],["result",6,[["array1",6]]]],[[["",0],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["lufactorized",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["",0],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["lufactorized",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["",0],["arraybase",3]],["result",6,[["array1",6]]]],[[["",0],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["lufactorized",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["",0]]],[[["",0]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["uplo",4]],["i8",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["uplo",4]],["uplo",4]],[[["",0],["",0]]],[[["",0]],["result",6]],[[["bkfactorized",3]]],[[],["result",6]],[[["bkfactorized",3]]],[[["",0]],["result",6,[["bkfactorized",3]]]],[[],["result",6,[["bkfactorized",3]]]],[[["uplo",4],["formatter",3]],["result",4,[["error",3]]]],[[]],[[]],[[]],[[]],[[["",0]],["result",6]],[[["bkfactorized",3]],["result",6]],[[],["result",6]],[[["bkfactorized",3]],["result",6,[["arraybase",3,[["ix2",6]]]]]],null,[[["",0]],["result",6]],[[["bkfactorized",3]]],[[],["result",6]],[[["bkfactorized",3]]],[[["",0],["arraybase",3]],["result",6,[["array1",6]]]],[[["",0],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["bkfactorized",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["uplo",4]],["uplo",4]],[[["",0]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,[[["",0],["bool",0],["bool",0]],["result",6]],[[["",0],["bool",0],["bool",0]],["result",6]],[[["bool",0],["bool",0]],["result",6]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["uvtflag",4]],["uvtflag",4]],[[["",0],["",0]]],[[["uvtflag",4],["uvtflag",4]],["bool",0]],[[]],[[]],[[["",0],["uvtflag",4]],["result",6]],[[["",0],["uvtflag",4]],["result",6]],[[["uvtflag",4]],["result",6]],[[["",0]]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,[[["",0]],["result",6]],null,null,null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["diag",4]],["diag",4]],[[["",0],["",0]]],[[["diag",4],["formatter",3]],["result",4,[["error",3]]]],[[]],[[]],[[["uplo",4]]],[[["",0],["uplo",4],["diag",4],["arraybase",3]],["result",6,[["array",6]]]],[[["",0],["uplo",4],["diag",4],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["uplo",4],["diag",4],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0]]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["",0]],["",0]],[[["tridiagonal",3]],["tridiagonal",3]],[[["lufactorizedtridiagonal",3]],["lufactorizedtridiagonal",3]],[[["",0],["",0]]],[[["",0],["",0]]],null,[[["",0]],["result",6]],[[["tridiagonal",3]],["result",6]],null,null,null,[[["tridiagonal",3],["tridiagonal",3]],["bool",0]],[[["lufactorizedtridiagonal",3],["lufactorizedtridiagonal",3]],["bool",0]],[[["",0]],["result",6,[["tridiagonal",3]]]],[[["",0]],["result",6,[["lufactorizedtridiagonal",3]]]],[[["tridiagonal",3]],["result",6,[["lufactorizedtridiagonal",3]]]],[[],["result",6,[["lufactorizedtridiagonal",3]]]],[[["tridiagonal",3]],["result",6,[["lufactorizedtridiagonal",3]]]],[[]],[[]],[[["tridiagonal",3]],["",0]],[[["tridiagonal",3]],["",0]],[[["tridiagonal",3]],["",0]],[[["tridiagonal",3]],["",0]],[[]],[[]],null,null,[[["tridiagonal",3],["tridiagonal",3]],["bool",0]],[[["lufactorizedtridiagonal",3],["lufactorizedtridiagonal",3]],["bool",0]],[[["tridiagonal",3],["normtype",4]],["result",6]],[[["",0]],["result",6]],[[["lufactorizedtridiagonal",3]],["result",6]],[[],["result",6]],[[["lufactorizedtridiagonal",3]],["result",6]],[[["",0],["arraybase",3]],["result",6,[["array",6]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix2",6]]]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix1",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix2",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix1",6]]]]]],[[["",0],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["arraybase",3,[["datamut",8]]]],["result",6,[["arraybase",3,[["datamut",8]]]]]],[[["tridiagonal",3],["arraybase",3,[["datamut",8],["ix2",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix2",6]]]]]],[[["tridiagonal",3],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3,[["datamut",8],["ix2",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix2",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["",0],["arraybase",3]],["result",6,[["array",6]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix1",6]]]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix2",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix2",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix1",6]]]]]],[[["",0],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["arraybase",3,[["datamut",8]]]],["result",6,[["arraybase",3,[["datamut",8]]]]]],[[["tridiagonal",3],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["tridiagonal",3],["arraybase",3,[["datamut",8],["ix2",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix2",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3,[["datamut",8],["ix2",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix2",6]]]]]],[[["",0],["arraybase",3]],["result",6,[["array",6]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix2",6]]]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix1",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix1",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["array",6,[["ix2",6]]]]]],[[["",0],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["tridiagonal",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["lufactorizedtridiagonal",3],["arraybase",3]],["result",6,[["arraybase",3]]]],[[["",0],["arraybase",3,[["datamut",8]]]],["result",6,[["arraybase",3,[["datamut",8]]]]]],[[["tridiagonal",3],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["tridiagonal",3],["arraybase",3,[["datamut",8],["ix2",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix2",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3,[["datamut",8],["ix1",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix1",6]]]]]],[[["lufactorizedtridiagonal",3],["arraybase",3,[["datamut",8],["ix2",6]]]],["result",6,[["arraybase",3,[["datamut",8],["ix2",6]]]]]],[[["",0]]],[[["",0]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["",0]],["typeid",3]],[[["",0]],["typeid",3]],[[]],[[]],null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[["",0]]],[[]],[[]],[[]],[[]],null,null,[[]],[[["",0]]],[[]],[[]],[[]],[[]],[[]],[[]],[[["",0]]],[[]],[[]],[[]],[[]],[[]],[[]],[[["i32",0]]],[[]],[[["",0]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]]],"p":[[4,"TruncatedOrder"],[3,"TruncatedEig"],[4,"UPLO"],[8,"Cholesky"],[8,"CholeskyInto"],[8,"InverseC"],[8,"InverseCInto"],[8,"DeterminantC"],[8,"DeterminantCInto"],[3,"CholeskyFactorized"],[8,"CholeskyInplace"],[8,"FactorizeC"],[8,"FactorizeCInto"],[8,"SolveC"],[3,"Diagonal"],[8,"AsDiagonal"],[8,"IntoDiagonal"],[8,"Eig"],[8,"EigVals"],[8,"Eigh"],[8,"EighInplace"],[8,"EighInto"],[8,"EigValsh"],[8,"EigValshInto"],[8,"EigValshInplace"],[8,"SymmetricSqrt"],[8,"SymmetricSqrtInto"],[4,"LinalgError"],[13,"Lapack"],[13,"Shape"],[13,"NotSquare"],[13,"NotStandardShape"],[13,"InvalidStride"],[8,"InnerProduct"],[4,"AppendResult"],[8,"Orthogonalizer"],[4,"Strategy"],[13,"Added"],[13,"Dependent"],[3,"Arnoldi"],[3,"Householder"],[3,"MGS"],[4,"MatrixLayout"],[8,"AllocatedArray"],[8,"AllocatedArrayMut"],[13,"F"],[13,"C"],[3,"LeastSquaresResult"],[8,"LeastSquaresSvd"],[8,"LeastSquaresSvdInPlace"],[8,"LeastSquaresSvdInto"],[4,"LobpcgResult"],[3,"TruncatedSvd"],[13,"Ok"],[13,"Err"],[13,"NoResult"],[4,"NormalizeAxis"],[8,"Norm"],[8,"LinearOperator"],[4,"NormType"],[8,"OperationNorm"],[8,"QR"],[8,"QRInto"],[8,"QRSquare"],[8,"QRSquareInto"],[8,"QRSquareInplace"],[4,"Transpose"],[8,"Inverse"],[8,"InverseInto"],[3,"LUFactorized"],[8,"Determinant"],[8,"DeterminantInto"],[8,"Factorize"],[8,"FactorizeInto"],[8,"ReciprocalConditionNum"],[8,"ReciprocalConditionNumInto"],[8,"Solve"],[8,"DeterminantH"],[8,"DeterminantHInto"],[8,"InverseH"],[8,"InverseHInto"],[3,"BKFactorized"],[8,"FactorizeH"],[8,"FactorizeHInto"],[8,"SolveH"],[8,"SVD"],[8,"SVDInto"],[8,"SVDInplace"],[4,"UVTFlag"],[8,"SVDDC"],[8,"SVDDCInto"],[8,"SVDDCInplace"],[8,"Trace"],[4,"Diag"],[8,"IntoTriangular"],[8,"SolveTriangular"],[8,"SolveTriangularInplace"],[8,"SolveTriangularInto"],[3,"LUFactorizedTridiagonal"],[3,"Tridiagonal"],[8,"DeterminantTridiagonal"],[8,"ExtractTridiagonal"],[8,"FactorizeTridiagonal"],[8,"FactorizeTridiagonalInto"],[8,"ReciprocalConditionNumTridiagonal"],[8,"ReciprocalConditionNumTridiagonalInto"],[8,"SolveTridiagonal"],[8,"SolveTridiagonalInplace"],[8,"Scalar"]]}\ +}'); +if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)}; +if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; diff --git a/search.js b/search.js new file mode 100644 index 00000000..8fd46df6 --- /dev/null +++ b/search.js @@ -0,0 +1 @@ +"use strict";(function(){const itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias",];const TY_PRIMITIVE=itemTypes.indexOf("primitive");const TY_KEYWORD=itemTypes.indexOf("keyword");const ROOT_PATH=typeof window!=="undefined"?window.rootPath:"../";function hasOwnPropertyRustdoc(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function printTab(nb){let iter=0;let foundCurrentTab=false;let foundCurrentResultSet=false;onEachLazy(document.getElementById("titles").childNodes,elem=>{if(nb===iter){addClass(elem,"selected");foundCurrentTab=true}else{removeClass(elem,"selected")}iter+=1});iter=0;onEachLazy(document.getElementById("results").childNodes,elem=>{if(nb===iter){addClass(elem,"active");foundCurrentResultSet=true}else{removeClass(elem,"active")}iter+=1});if(foundCurrentTab&&foundCurrentResultSet){searchState.currentTab=nb}else if(nb!==0){printTab(0)}}const levenshtein_row2=[];function levenshtein(s1,s2){if(s1===s2){return 0}const s1_len=s1.length,s2_len=s2.length;if(s1_len&&s2_len){let i1=0,i2=0,a,b,c,c2;const row=levenshtein_row2;while(i1-".indexOf(c)!==-1}function isStopCharacter(c){return isWhitespace(c)||isEndCharacter(c)}function isErrorCharacter(c){return"()".indexOf(c)!==-1}function itemTypeFromName(typename){for(let i=0,len=itemTypes.length;i0){throw new Error("Cannot use literal search when there is more than one element")}parserState.pos+=1;const start=parserState.pos;const end=getIdentEndPosition(parserState);if(parserState.pos>=parserState.length){throw new Error("Unclosed `\"`")}else if(parserState.userQuery[end]!=="\""){throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`)}else if(start===end){throw new Error("Cannot have empty string element")}parserState.pos+=1;query.literalSearch=true}function isPathStart(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="::"}function isReturnArrow(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="->"}function isIdentCharacter(c){return(c==="_"||(c>="0"&&c<="9")||(c>="a"&&c<="z")||(c>="A"&&c<="Z"))}function isSeparatorCharacter(c){return c===","||isWhitespaceCharacter(c)}function isWhitespaceCharacter(c){return c===" "||c==="\t"}function createQueryElement(query,parserState,name,generics,isInGenerics){if(name==="*"||(name.length===0&&generics.length===0)){return}if(query.literalSearch&&parserState.totalElems-parserState.genericsElems>0){throw new Error("You cannot have more than one element if you use quotes")}const pathSegments=name.split("::");if(pathSegments.length>1){for(let i=0,len=pathSegments.length;i=end){throw new Error("Found generics without a path")}parserState.pos+=1;getItemsBefore(query,parserState,generics,">")}if(start>=end&&generics.length===0){return}elems.push(createQueryElement(query,parserState,parserState.userQuery.slice(start,end),generics,isInGenerics))}function getItemsBefore(query,parserState,elems,endChar){let foundStopChar=true;while(parserState.pos"){extra="`<`"}else if(endChar===""){extra="`->`"}throw new Error("Unexpected `"+c+"` after "+extra)}if(!foundStopChar){if(endChar!==""){throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``)}throw new Error(`Expected \`,\` or \` \`, found \`${c}\``)}const posBefore=parserState.pos;getNextElem(query,parserState,elems,endChar===">");if(posBefore===parserState.pos){parserState.pos+=1}foundStopChar=false}parserState.pos+=1}function checkExtraTypeFilterCharacters(parserState){const query=parserState.userQuery;for(let pos=0;pos"){if(isReturnArrow(parserState)){break}throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`)}throw new Error(`Unexpected \`${c}\``)}else if(c===":"&&!isPathStart(parserState)){if(parserState.typeFilter!==null){throw new Error("Unexpected `:`")}if(query.elems.length===0){throw new Error("Expected type filter before `:`")}else if(query.elems.length!==1||parserState.totalElems!==1){throw new Error("Unexpected `:`")}else if(query.literalSearch){throw new Error("You cannot use quotes on type filter")}checkExtraTypeFilterCharacters(parserState);parserState.typeFilter=query.elems.pop().name;parserState.pos+=1;parserState.totalElems=0;query.literalSearch=false;foundStopChar=true;continue}if(!foundStopChar){if(parserState.typeFilter!==null){throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``)}throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``)}before=query.elems.length;getNextElem(query,parserState,query.elems,false);if(query.elems.length===before){parserState.pos+=1}foundStopChar=false}while(parserState.pos`")}break}else{parserState.pos+=1}}}function newParsedQuery(userQuery){return{original:userQuery,userQuery:userQuery.toLowerCase(),typeFilter:NO_TYPE_FILTER,elems:[],returned:[],foundElems:0,literalSearch:false,error:null,}}function buildUrl(search,filterCrates){let extra="?search="+encodeURIComponent(search);if(filterCrates!==null){extra+="&filter-crate="+encodeURIComponent(filterCrates)}return getNakedUrl()+extra+window.location.hash}function getFilterCrates(){const elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnPropertyRustdoc(rawSearchIndex,elem.value)){return elem.value}return null}function parseQuery(userQuery){userQuery=userQuery.trim();const parserState={length:userQuery.length,pos:0,totalElems:0,genericsElems:0,typeFilter:null,userQuery:userQuery.toLowerCase(),};let query=newParsedQuery(userQuery);try{parseInput(query,parserState);if(parserState.typeFilter!==null){let typeFilter=parserState.typeFilter;if(typeFilter==="const"){typeFilter="constant"}query.typeFilter=itemTypeFromName(typeFilter)}}catch(err){query=newParsedQuery(userQuery);query.error=err.message;query.typeFilter=-1;return query}if(!query.literalSearch){query.literalSearch=parserState.totalElems>1}query.foundElems=query.elems.length+query.returned.length;return query}function createQueryResults(results_in_args,results_returned,results_others,parsedQuery){return{"in_args":results_in_args,"returned":results_returned,"others":results_others,"query":parsedQuery,}}function execQuery(parsedQuery,searchWords,filterCrates,currentCrate){const results_others={},results_in_args={},results_returned={};function transformResults(results){const duplicates={};const out=[];for(const result of results){if(result.id>-1){const obj=searchIndex[result.id];obj.lev=result.lev;const res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;if(duplicates[obj.fullPath]){continue}duplicates[obj.fullPath]=true;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out}function sortResults(results,isType,preferredCrate){const userQuery=parsedQuery.userQuery;const ar=[];for(const entry in results){if(hasOwnPropertyRustdoc(results,entry)){const result=results[entry];result.word=searchWords[result.id];result.item=searchIndex[result.id]||{};ar.push(result)}}results=ar;if(results.length===0){return[]}results.sort((aaa,bbb)=>{let a,b;a=(aaa.word!==userQuery);b=(bbb.word!==userQuery);if(a!==b){return a-b}a=(aaa.lev);b=(bbb.lev);if(a!==b){return a-b}a=(aaa.item.crate!==preferredCrate);b=(bbb.item.crate!==preferredCrate);if(a!==b){return a-b}a=aaa.word.length;b=bbb.word.length;if(a!==b){return a-b}a=aaa.word;b=bbb.word;if(a!==b){return(a>b?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});let nameSplit=null;if(parsedQuery.elems.length===1){const hasPath=typeof parsedQuery.elems[0].path==="undefined";nameSplit=hasPath?null:parsedQuery.elems[0].path}for(const result of results){if(result.dontValidate){continue}const name=result.item.name.toLowerCase(),path=result.item.path.toLowerCase(),parent=result.item.parent;if(!isType&&!validateResult(name,path,nameSplit,parent)){result.id=-1}}return transformResults(results)}function checkGenerics(row,elem,defaultLev){if(row.length<=GENERICS_DATA||row[GENERICS_DATA].length===0){return elem.generics.length===0?defaultLev:MAX_LEV_DISTANCE+1}else if(row[GENERICS_DATA].length>0&&row[GENERICS_DATA][0][NAME]===""){if(row.length>GENERICS_DATA){return checkGenerics(row[GENERICS_DATA][0],elem,defaultLev)}return elem.generics.length===0?defaultLev:MAX_LEV_DISTANCE+1}let elem_name;if(elem.generics.length>0&&row[GENERICS_DATA].length>=elem.generics.length){const elems=Object.create(null);for(const entry of row[GENERICS_DATA]){elem_name=entry[NAME];if(elem_name===""){if(checkGenerics(entry,elem,MAX_LEV_DISTANCE+1)!==0){return MAX_LEV_DISTANCE+1}continue}if(elems[elem_name]===undefined){elems[elem_name]=0}elems[elem_name]+=1}for(const generic of elem.generics){let match=null;if(elems[generic.name]){match=generic.name}else{for(elem_name in elems){if(!hasOwnPropertyRustdoc(elems,elem_name)){continue}if(elem_name===generic){match=elem_name;break}}}if(match===null){return MAX_LEV_DISTANCE+1}elems[match]-=1;if(elems[match]===0){delete elems[match]}}return 0}return MAX_LEV_DISTANCE+1}function checkIfInGenerics(row,elem){let lev=MAX_LEV_DISTANCE+1;for(const entry of row[GENERICS_DATA]){lev=Math.min(checkType(entry,elem,true),lev);if(lev===0){break}}return lev}function checkType(row,elem,literalSearch){if(row[NAME].length===0){if(row.length>GENERICS_DATA){return checkIfInGenerics(row,elem)}return MAX_LEV_DISTANCE+1}let lev=levenshtein(row[NAME],elem.name);if(literalSearch){if(lev!==0){if(elem.generics.length===0){const checkGeneric=(row.length>GENERICS_DATA&&row[GENERICS_DATA].length>0);if(checkGeneric&&row[GENERICS_DATA].findIndex(tmp_elem=>tmp_elem[NAME]===elem.name)!==-1){return 0}}return MAX_LEV_DISTANCE+1}else if(elem.generics.length>0){return checkGenerics(row,elem,MAX_LEV_DISTANCE+1)}return 0}else if(row.length>GENERICS_DATA){if(elem.generics.length===0){if(lev===0){return 0}lev=checkIfInGenerics(row,elem);return lev+0.5}else if(lev>MAX_LEV_DISTANCE){return checkIfInGenerics(row,elem)}else{const tmp_lev=checkGenerics(row,elem,lev);if(tmp_lev>MAX_LEV_DISTANCE){return MAX_LEV_DISTANCE+1}return(tmp_lev+lev)/2}}else if(elem.generics.length>0){return MAX_LEV_DISTANCE+1}return lev}function findArg(row,elem,typeFilter){let lev=MAX_LEV_DISTANCE+1;if(row&&row.type&&row.type[INPUTS_DATA]&&row.type[INPUTS_DATA].length>0){for(const input of row.type[INPUTS_DATA]){if(!typePassesFilter(typeFilter,input[1])){continue}lev=Math.min(lev,checkType(input,elem,parsedQuery.literalSearch));if(lev===0){return 0}}}return parsedQuery.literalSearch?MAX_LEV_DISTANCE+1:lev}function checkReturned(row,elem,typeFilter){let lev=MAX_LEV_DISTANCE+1;if(row&&row.type&&row.type.length>OUTPUT_DATA){let ret=row.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(const ret_ty of ret){if(!typePassesFilter(typeFilter,ret_ty[1])){continue}lev=Math.min(lev,checkType(ret_ty,elem,parsedQuery.literalSearch));if(lev===0){return 0}}}return parsedQuery.literalSearch?MAX_LEV_DISTANCE+1:lev}function checkPath(contains,ty){if(contains.length===0){return 0}let ret_lev=MAX_LEV_DISTANCE+1;const path=ty.path.split("::");if(ty.parent&&ty.parent.name){path.push(ty.parent.name.toLowerCase())}const length=path.length;const clength=contains.length;if(clength>length){return MAX_LEV_DISTANCE+1}for(let i=0;ilength){break}let lev_total=0;let aborted=false;for(let x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(!aborted){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER||filter===type)return true;const name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates,currentCrate){const lowerQuery=query.toLowerCase();const aliases=[];const crateAliases=[];if(filterCrates!==null){if(ALIASES[filterCrates]&&ALIASES[filterCrates][lowerQuery]){const query_aliases=ALIASES[filterCrates][lowerQuery];for(const alias of query_aliases){aliases.push(createAliasFromItem(searchIndex[alias]))}}}else{Object.keys(ALIASES).forEach(crate=>{if(ALIASES[crate][lowerQuery]){const pushTo=crate===currentCrate?crateAliases:aliases;const query_aliases=ALIASES[crate][lowerQuery];for(const alias of query_aliases){pushTo.push(createAliasFromItem(searchIndex[alias]))}}})}const sortFunc=(aaa,bbb)=>{if(aaa.path{alias.alias=query;const res=buildHrefAndPath(alias);alias.displayPath=pathSplitter(res[0]);alias.fullPath=alias.displayPath+alias.name;alias.href=res[1];ret.others.unshift(alias);if(ret.others.length>MAX_RESULTS){ret.others.pop()}};aliases.forEach(pushFunc);crateAliases.forEach(pushFunc)}function addIntoResults(results,fullId,id,index,lev){if(lev===0||(!parsedQuery.literalSearch&&lev<=MAX_LEV_DISTANCE)){if(results[fullId]!==undefined){const result=results[fullId];if(result.dontValidate||result.lev<=lev){return}}results[fullId]={id:id,index:index,dontValidate:parsedQuery.literalSearch,lev:lev,}}}function handleSingleArg(row,pos,elem,results_others,results_in_args,results_returned){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let lev,lev_add=0,index=-1;const fullId=row.id;const in_args=findArg(row,elem,parsedQuery.typeFilter);const returned=checkReturned(row,elem,parsedQuery.typeFilter);addIntoResults(results_in_args,fullId,pos,index,in_args);addIntoResults(results_returned,fullId,pos,index,returned);if(!typePassesFilter(parsedQuery.typeFilter,row.ty)){return}const searchWord=searchWords[pos];if(parsedQuery.literalSearch){if(searchWord===elem.name){addIntoResults(results_others,fullId,pos,-1,0)}return}if(elem.name.length===0){if(row.type!==null){lev=checkGenerics(row.type,elem,MAX_LEV_DISTANCE+1);addIntoResults(results_others,fullId,pos,index,lev)}return}if(elem.fullPath.length>1){lev=checkPath(elem.pathWithoutLast,row);if(lev>MAX_LEV_DISTANCE||(parsedQuery.literalSearch&&lev!==0)){return}else if(lev>0){lev_add=lev/10}}if(searchWord.indexOf(elem.pathLast)>-1||row.normalizedName.indexOf(elem.pathLast)>-1){index=row.normalizedName.indexOf(elem.pathLast)}lev=levenshtein(searchWord,elem.pathLast);if(lev>0&&elem.pathLast.length>2&&searchWord.indexOf(elem.pathLast)>-1){if(elem.pathLast.length<6){lev=1}else{lev=0}}lev+=lev_add;if(lev>MAX_LEV_DISTANCE){return}else if(index!==-1&&elem.fullPath.length<2){lev-=1}if(lev<0){lev=0}addIntoResults(results_others,fullId,pos,index,lev)}function handleArgs(row,pos,results){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let totalLev=0;let nbLev=0;function checkArgs(elems,callback){for(const elem of elems){const lev=callback(row,elem,NO_TYPE_FILTER);if(lev<=1){nbLev+=1;totalLev+=lev}else{return false}}return true}if(!checkArgs(parsedQuery.elems,findArg)){return}if(!checkArgs(parsedQuery.returned,checkReturned)){return}if(nbLev===0){return}const lev=Math.round(totalLev/nbLev);addIntoResults(results,row.id,pos,0,lev)}function innerRunQuery(){let elem,i,nSearchWords,in_returned,row;if(parsedQuery.foundElems===1){if(parsedQuery.elems.length===1){elem=parsedQuery.elems[0];for(i=0,nSearchWords=searchWords.length;i0){for(i=0,nSearchWords=searchWords.length;i-1||path.indexOf(key)>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(key)>-1)||levenshtein(name,key)<=MAX_LEV_DISTANCE)){return false}}return true}function nextTab(direction){const next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){const target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#titles > button").item(searchState.currentTab);if(target){target.focus()}}function buildHrefAndPath(item){let displayPath;let href;const type=itemTypes[item.ty];const name=item.name;let path=item.path;if(type==="mod"){displayPath=path+"::";href=ROOT_PATH+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="import"){displayPath=item.path+"::";href=ROOT_PATH+item.path.replace(/::/g,"/")+"/index.html#reexport."+name}else if(type==="primitive"||type==="keyword"){displayPath="";href=ROOT_PATH+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=ROOT_PATH+name+"/index.html"}else if(item.parent!==undefined){const myparent=item.parent;let anchor="#"+type+"."+name;const parentType=itemTypes[myparent.ty];let pageType=parentType;let pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){const enumNameIdx=item.path.lastIndexOf("::");const enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=ROOT_PATH+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=ROOT_PATH+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){const h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){const tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){let extraClass="";if(display===true){extraClass=" active"}const output=document.createElement("div");let length=0;if(array.length>0){output.className="search-results "+extraClass;array.forEach(item=>{const name=item.name;const type=itemTypes[item.ty];length+=1;let extra="";if(type==="primitive"){extra=" (primitive type)"}else if(type==="keyword"){extra=" (keyword)"}const link=document.createElement("a");link.className="result-"+type;link.href=item.href;const wrapper=document.createElement("div");const resultName=document.createElement("div");resultName.className="result-name";if(item.is_alias){const alias=document.createElement("span");alias.className="alias";const bold=document.createElement("b");bold.innerText=item.alias;alias.appendChild(bold);alias.insertAdjacentHTML("beforeend"," - see ");resultName.appendChild(alias)}resultName.insertAdjacentHTML("beforeend",item.displayPath+""+name+extra+"");wrapper.appendChild(resultName);const description=document.createElement("div");description.className="desc";const spanDesc=document.createElement("span");spanDesc.insertAdjacentHTML("beforeend",item.desc);description.appendChild(spanDesc);wrapper.appendChild(description);link.appendChild(wrapper);output.appendChild(link)})}else if(query.error===null){output.className="search-failed"+extraClass;output.innerHTML="No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(searchState.currentTab===tabNb){return""}return""}function showResults(results,go_to_first,filterCrates){const search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true"&&(!search.firstChild||search.firstChild.innerText!==searchState.loadingText))){const elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}if(results.query===undefined){results.query=parseQuery(searchState.input.value)}currentResults=results.query.userQuery;const ret_others=addTab(results.others,results.query,true);const ret_in_args=addTab(results.in_args,results.query,false);const ret_returned=addTab(results.returned,results.query,false);let currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}let crates="";const crates_list=Object.keys(rawSearchIndex);if(crates_list.length>1){crates=" in "}let typeFilter="";if(results.query.typeFilter!==NO_TYPE_FILTER){typeFilter=" (type: "+escape(itemTypes[results.query.typeFilter])+")"}let output="
"+`

Results for ${escape(results.query.userQuery)}`+`${typeFilter}

${crates}
`;if(results.query.error!==null){output+=`

Query parser error: "${results.query.error}".

`;output+="
"+makeTabHeader(0,"In Names",ret_others[1])+"
";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"}else{const signatureTabTitle=results.query.elems.length===0?"In Function Return Types":results.query.returned.length===0?"In Function Parameters":"In Function Signatures";output+="
"+makeTabHeader(0,signatureTabTitle,ret_others[1])+"
";currentTab=0}const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;const crateSearch=document.getElementById("crate-search");if(crateSearch){crateSearch.addEventListener("input",updateCrate)}search.appendChild(resultsElem);searchState.showResults(search);const elems=document.getElementById("titles").childNodes;searchState.focusedByTab=[];let i=0;for(const elem of elems){const j=i;elem.onclick=()=>printTab(j);searchState.focusedByTab.push(null);i+=1}printTab(currentTab)}function search(e,forced){const params=searchState.getQueryStringParams();const query=parseQuery(searchState.input.value.trim());if(e){e.preventDefault()}if(!forced&&query.userQuery===currentResults){if(query.userQuery.length>0){putBackSearch()}return}let filterCrates=getFilterCrates();if(filterCrates===null&¶ms["filter-crate"]!==undefined){filterCrates=params["filter-crate"]}searchState.title="Results for "+query.original+" - Rust";if(browserSupportsHistoryApi()){const newURL=buildUrl(query.original,filterCrates);if(!history.state&&!params.search){history.pushState(null,"",newURL)}else{history.replaceState(null,"",newURL)}}showResults(execQuery(query,searchWords,filterCrates,window.currentCrate),params.go_to_first,filterCrates)}function buildIndex(rawSearchIndex){searchIndex=[];const searchWords=[];let i,word;let currentIndex=0;let id=0;for(const crate in rawSearchIndex){if(!hasOwnPropertyRustdoc(rawSearchIndex,crate)){continue}let crateSize=0;const crateCorpus=rawSearchIndex[crate];searchWords.push(crate);const crateRow={crate:crate,ty:1,name:crate,path:"",desc:crateCorpus.doc,parent:undefined,type:null,id:id,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),};id+=1;searchIndex.push(crateRow);currentIndex+=1;const itemTypes=crateCorpus.t;const itemNames=crateCorpus.n;const itemPaths=crateCorpus.q;const itemDescs=crateCorpus.d;const itemParentIdxs=crateCorpus.i;const itemFunctionSearchTypes=crateCorpus.f;const paths=crateCorpus.p;const aliases=crateCorpus.a;let len=paths.length;for(i=0;i0?paths[itemParentIdxs[i]-1]:undefined,type:itemFunctionSearchTypes[i],id:id,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),};id+=1;searchIndex.push(row);lastPath=row.path;crateSize+=1}if(aliases){ALIASES[crate]=Object.create(null);for(const alias_name in aliases){if(!hasOwnPropertyRustdoc(aliases,alias_name)){continue}if(!hasOwnPropertyRustdoc(ALIASES[crate],alias_name)){ALIASES[crate][alias_name]=[]}for(const local_alias of aliases[alias_name]){ALIASES[crate][alias_name].push(local_alias+currentIndex)}}}currentIndex+=crateSize}return searchWords}function onSearchSubmit(e){e.preventDefault();searchState.clearInputTimeout();search()}function putBackSearch(){const search_input=searchState.input;if(!searchState.input){return}if(search_input.value!==""&&!searchState.isDisplayed()){searchState.showResults();if(browserSupportsHistoryApi()){history.replaceState(null,"",buildUrl(search_input.value,getFilterCrates()))}document.title=searchState.title}}function registerSearchEvents(){const params=searchState.getQueryStringParams();if(searchState.input.value===""){searchState.input.value=params.search||""}const searchAfter500ms=()=>{searchState.clearInputTimeout();if(searchState.input.value.length===0){if(browserSupportsHistoryApi()){history.replaceState(null,window.currentCrate+" - Rust",getNakedUrl()+window.location.hash)}searchState.hideResults()}else{searchState.timeout=setTimeout(search,500)}};searchState.input.onkeyup=searchAfter500ms;searchState.input.oninput=searchAfter500ms;document.getElementsByClassName("search-form")[0].onsubmit=onSearchSubmit;searchState.input.onchange=e=>{if(e.target!==document.activeElement){return}searchState.clearInputTimeout();setTimeout(search,0)};searchState.input.onpaste=searchState.input.onchange;searchState.outputElement().addEventListener("keydown",e=>{if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey){return}if(e.which===38){const previous=document.activeElement.previousElementSibling;if(previous){previous.focus()}else{searchState.focus()}e.preventDefault()}else if(e.which===40){const next=document.activeElement.nextElementSibling;if(next){next.focus()}const rect=document.activeElement.getBoundingClientRect();if(window.innerHeight-rect.bottom{if(e.which===40){focusSearchResult();e.preventDefault()}});searchState.input.addEventListener("focus",()=>{putBackSearch()});searchState.input.addEventListener("blur",()=>{searchState.input.placeholder=searchState.input.origPlaceholder});if(browserSupportsHistoryApi()){const previousTitle=document.title;window.addEventListener("popstate",e=>{const params=searchState.getQueryStringParams();document.title=previousTitle;currentResults=null;if(params.search&¶ms.search.length>0){searchState.input.value=params.search;search(e)}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=()=>{const qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}function updateCrate(ev){if(ev.target.value==="All crates"){const params=searchState.getQueryStringParams();const query=searchState.input.value.trim();if(!history.state&&!params.search){history.pushState(null,"",buildUrl(query,null))}else{history.replaceState(null,"",buildUrl(query,null))}}currentResults=null;search(undefined,true)}const searchWords=buildIndex(rawSearchIndex);if(typeof window!=="undefined"){registerSearchEvents();if(window.searchState.getQueryStringParams().search){search()}}if(typeof exports!=="undefined"){exports.initSearch=initSearch;exports.execQuery=execQuery;exports.parseQuery=parseQuery}return searchWords}if(typeof window!=="undefined"){window.initSearch=initSearch;if(window.searchIndex!==undefined){initSearch(window.searchIndex)}}else{initSearch({})}})() \ No newline at end of file diff --git a/settings.css b/settings.css new file mode 100644 index 00000000..2be35b25 --- /dev/null +++ b/settings.css @@ -0,0 +1 @@ +.setting-line{margin:0.6em 0 0.6em 0.3em;position:relative;}.setting-line .choices{display:flex;flex-wrap:wrap;}.setting-line .radio-line input{margin-right:0.3em;height:1.2rem;width:1.2rem;border:1px solid;outline:none;-webkit-appearance:none;cursor:pointer;border-radius:50%;}.setting-line .radio-line input+span{padding-bottom:1px;}.radio-line .setting-name{width:100%;}.radio-line .choice{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:flex;align-items:center;cursor:pointer;}.radio-line .choice+.choice{margin-left:0.5em;}.toggle{position:relative;display:inline-block;width:100%;height:27px;margin-right:20px;display:flex;align-items:center;cursor:pointer;}.toggle input{opacity:0;position:absolute;}.slider{position:relative;width:45px;display:block;height:28px;margin-right:20px;cursor:pointer;background-color:#ccc;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;transition:.3s;}input:checked+.slider:before{transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;}div#settings{position:absolute;right:0;z-index:1;display:block;margin-top:7px;border-radius:3px;border:1px solid;}#settings .setting-line{margin:1.2em 0.6em;}div#settings::before{content:'';position:absolute;right:11px;border:solid;border-width:1px 1px 0 0;display:inline-block;padding:4px;transform:rotate(-45deg);top:-5px;} \ No newline at end of file diff --git a/settings.html b/settings.html new file mode 100644 index 00000000..7e5d4afb --- /dev/null +++ b/settings.html @@ -0,0 +1,25 @@ +Rustdoc settings + + + + + + +

Rustdoc settings

Back
+ \ No newline at end of file diff --git a/settings.js b/settings.js new file mode 100644 index 00000000..35d65a9f --- /dev/null +++ b/settings.js @@ -0,0 +1,11 @@ +"use strict";(function(){const isSettingsPage=window.location.pathname.endsWith("/settings.html");function changeSetting(settingName,value){updateLocalStorage(settingName,value);switch(settingName){case"theme":case"preferred-dark-theme":case"preferred-light-theme":case"use-system-theme":updateSystemTheme();updateLightAndDark();break}}function handleKey(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey){return}switch(getVirtualKey(ev)){case"Enter":case"Return":case"Space":ev.target.checked=!ev.target.checked;ev.preventDefault();break}}function showLightAndDark(){addClass(document.getElementById("theme").parentElement,"hidden");removeClass(document.getElementById("preferred-light-theme").parentElement,"hidden");removeClass(document.getElementById("preferred-dark-theme").parentElement,"hidden")}function hideLightAndDark(){addClass(document.getElementById("preferred-light-theme").parentElement,"hidden");addClass(document.getElementById("preferred-dark-theme").parentElement,"hidden");removeClass(document.getElementById("theme").parentElement,"hidden")}function updateLightAndDark(){if(getSettingValue("use-system-theme")!=="false"){showLightAndDark()}else{hideLightAndDark()}}function setEvents(settingsElement){updateLightAndDark();onEachLazy(settingsElement.getElementsByClassName("slider"),elem=>{const toggle=elem.previousElementSibling;const settingId=toggle.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)};toggle.onkeyup=handleKey;toggle.onkeyrelease=handleKey});onEachLazy(settingsElement.getElementsByClassName("select-wrapper"),elem=>{const select=elem.getElementsByTagName("select")[0];const settingId=select.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){select.value=settingValue}select.onchange=function(){changeSetting(this.id,this.value)}});onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"),elem=>{const settingId=elem.name;const settingValue=getSettingValue(settingId);if(settingValue!==null&&settingValue!=="null"){elem.checked=settingValue===elem.value}elem.addEventListener("change",ev=>{changeSetting(ev.target.name,ev.target.value)})})}function buildSettingsPageSections(settings){let output="";for(const setting of settings){output+="
";const js_data_name=setting["js_name"];const setting_name=setting["name"];if(setting["options"]!==undefined){output+=`
\ + ${setting_name}\ +
`;onEach(setting["options"],option=>{const checked=option===setting["default"]?" checked":"";output+=``});output+="
"}else{const checked=setting["default"]===true?" checked":"";output+=``}output+="
"}return output}function buildSettingsPage(){const themes=getVar("themes").split(",");const settings=[{"name":"Use system theme","js_name":"use-system-theme","default":true,},{"name":"Theme","js_name":"theme","default":"light","options":themes,},{"name":"Preferred light theme","js_name":"preferred-light-theme","default":"light","options":themes,},{"name":"Preferred dark theme","js_name":"preferred-dark-theme","default":"dark","options":themes,},{"name":"Auto-hide item contents for large items","js_name":"auto-hide-large-items","default":true,},{"name":"Auto-hide item methods' documentation","js_name":"auto-hide-method-docs","default":false,},{"name":"Auto-hide trait implementation documentation","js_name":"auto-hide-trait-implementations","default":false,},{"name":"Directly go to item in search if there is only one result","js_name":"go-to-only-result","default":false,},{"name":"Show line numbers on code examples","js_name":"line-numbers","default":false,},{"name":"Disable keyboard shortcuts","js_name":"disable-shortcuts","default":false,},];const elementKind=isSettingsPage?"section":"div";const innerHTML=`
${buildSettingsPageSections(settings)}
`;const el=document.createElement(elementKind);el.id="settings";el.innerHTML=innerHTML;if(isSettingsPage){document.getElementById(MAIN_ID).appendChild(el)}else{el.setAttribute("tabindex","-1");getSettingsButton().appendChild(el)}return el}const settingsMenu=buildSettingsPage();function displaySettings(){settingsMenu.style.display=""}function elemIsInParent(elem,parent){while(elem&&elem!==document.body){if(elem===parent){return true}elem=elem.parentElement}return false}function blurHandler(event){const settingsButton=getSettingsButton();if(!elemIsInParent(document.activeElement,settingsButton)&&!elemIsInParent(event.relatedTarget,settingsButton)){window.hideSettings()}}if(isSettingsPage){getSettingsButton().onclick=function(event){event.preventDefault()}}else{const settingsButton=getSettingsButton();const settingsMenu=document.getElementById("settings");window.hideSettings=function(){settingsMenu.style.display="none"};settingsButton.onclick=function(event){if(elemIsInParent(event.target,settingsMenu)){return}event.preventDefault();if(settingsMenu.style.display!=="none"){window.hideSettings()}else{displaySettings()}};settingsButton.onblur=blurHandler;settingsButton.querySelector("a").onblur=blurHandler;onEachLazy(settingsMenu.querySelectorAll("input"),el=>{el.onblur=blurHandler});settingsMenu.onblur=blurHandler}setTimeout(()=>{setEvents(settingsMenu);if(!isSettingsPage){displaySettings()}removeClass(getSettingsButton(),"rotate")},0)})() \ No newline at end of file diff --git a/source-files.js b/source-files.js new file mode 100644 index 00000000..e50d2763 --- /dev/null +++ b/source-files.js @@ -0,0 +1,4 @@ +var sourcesIndex = {}; +sourcesIndex["lax"] = {"name":"","files":["cholesky.rs","eig.rs","eigh.rs","error.rs","layout.rs","least_squares.rs","lib.rs","opnorm.rs","qr.rs","rcond.rs","solve.rs","solveh.rs","svd.rs","svddc.rs","triangular.rs","tridiagonal.rs"]}; +sourcesIndex["ndarray_linalg"] = {"name":"","dirs":[{"name":"krylov","files":["arnoldi.rs","householder.rs","mgs.rs","mod.rs"]},{"name":"lobpcg","files":["eig.rs","lobpcg.rs","mod.rs","svd.rs"]}],"files":["assert.rs","cholesky.rs","convert.rs","diagonal.rs","eig.rs","eigh.rs","error.rs","generate.rs","inner.rs","layout.rs","least_squares.rs","lib.rs","norm.rs","operator.rs","opnorm.rs","qr.rs","solve.rs","solveh.rs","svd.rs","svddc.rs","trace.rs","triangular.rs","tridiagonal.rs","types.rs"]}; +createSourceSidebar(); diff --git a/source-script.js b/source-script.js new file mode 100644 index 00000000..c8856707 --- /dev/null +++ b/source-script.js @@ -0,0 +1 @@ +"use strict";(function(){const rootPath=document.getElementById("rustdoc-vars").attributes["data-root-path"].value;function createDirEntry(elem,parent,fullPath,hasFoundFile){const name=document.createElement("div");name.className="name";fullPath+=elem["name"]+"/";name.onclick=ev=>{if(hasClass(ev.target,"expand")){removeClass(ev.target,"expand")}else{addClass(ev.target,"expand")}};name.innerText=elem["name"];const children=document.createElement("div");children.className="children";const folders=document.createElement("div");folders.className="folders";if(elem.dirs){for(const dir of elem.dirs){if(createDirEntry(dir,folders,fullPath,hasFoundFile)){addClass(name,"expand");hasFoundFile=true}}}children.appendChild(folders);const files=document.createElement("div");files.className="files";if(elem.files){for(const file_text of elem.files){const file=document.createElement("a");file.innerText=file_text;file.href=rootPath+"src/"+fullPath+file_text+".html";const w=window.location.href.split("#")[0];if(!hasFoundFile&&w===file.href){file.className="selected";addClass(name,"expand");hasFoundFile=true}files.appendChild(file)}}children.appendChild(files);parent.appendChild(name);parent.appendChild(children);return hasFoundFile}function toggleSidebar(){const child=this.children[0];if(child.innerText===">"){addClass(document.documentElement,"source-sidebar-expanded");child.innerText="<";updateLocalStorage("source-sidebar-show","true")}else{removeClass(document.documentElement,"source-sidebar-expanded");child.innerText=">";updateLocalStorage("source-sidebar-show","false")}}function createSidebarToggle(){const sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;const inner=document.createElement("div");if(getCurrentValue("source-sidebar-show")==="true"){inner.innerText="<"}else{inner.innerText=">"}sidebarToggle.appendChild(inner);return sidebarToggle}function createSourceSidebar(){const container=document.querySelector("nav.sidebar");const sidebarToggle=createSidebarToggle();container.insertBefore(sidebarToggle,container.firstChild);const sidebar=document.createElement("div");sidebar.id="source-sidebar";let hasFoundFile=false;const title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(key=>{sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",hasFoundFile)});container.appendChild(sidebar);const selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}const lineNumbersRegex=/^#?(\d+)(?:-(\d+))?$/;function highlightSourceLines(match){if(typeof match==="undefined"){match=window.location.hash.match(lineNumbersRegex)}if(!match){return}let from=parseInt(match[1],10);let to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to{onEachLazy(e.getElementsByTagName("span"),i_e=>{removeClass(i_e,"line-highlighted")})});for(let i=from;i<=to;++i){elem=document.getElementById(i);if(!elem){break}addClass(elem,"line-highlighted")}}const handleSourceHighlight=(function(){let prev_line_id=0;const set_fragment=name=>{const x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return ev=>{let cur_line_id=parseInt(ev.target.id,10);if(isNaN(cur_line_id)){return}ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){const tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",()=>{const match=window.location.hash.match(lineNumbersRegex);if(match){return highlightSourceLines(match)}});onEachLazy(document.getElementsByClassName("line-numbers"),el=>{el.addEventListener("click",handleSourceHighlight)});highlightSourceLines();window.createSourceSidebar=createSourceSidebar})() \ No newline at end of file diff --git a/src/lax/cholesky.rs.html b/src/lax/cholesky.rs.html new file mode 100644 index 00000000..5c6d4c11 --- /dev/null +++ b/src/lax/cholesky.rs.html @@ -0,0 +1,264 @@ +cholesky.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+
//! Cholesky decomposition
+
+use super::*;
+use crate::{error::*, layout::*};
+use cauchy::*;
+
+pub trait Cholesky_: Sized {
+    /// Cholesky: wrapper of `*potrf`
+    ///
+    /// **Warning: Only the portion of `a` corresponding to `UPLO` is written.**
+    fn cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()>;
+
+    /// Wrapper of `*potri`
+    ///
+    /// **Warning: Only the portion of `a` corresponding to `UPLO` is written.**
+    fn inv_cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()>;
+
+    /// Wrapper of `*potrs`
+    fn solve_cholesky(l: MatrixLayout, uplo: UPLO, a: &[Self], b: &mut [Self]) -> Result<()>;
+}
+
+macro_rules! impl_cholesky {
+    ($scalar:ty, $trf:path, $tri:path, $trs:path) => {
+        impl Cholesky_ for $scalar {
+            fn cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()> {
+                let (n, _) = l.size();
+                if matches!(l, MatrixLayout::C { .. }) {
+                    square_transpose(l, a);
+                }
+                let mut info = 0;
+                unsafe {
+                    $trf(uplo.as_ptr(), &n, AsPtr::as_mut_ptr(a), &n, &mut info);
+                }
+                info.as_lapack_result()?;
+                if matches!(l, MatrixLayout::C { .. }) {
+                    square_transpose(l, a);
+                }
+                Ok(())
+            }
+
+            fn inv_cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()> {
+                let (n, _) = l.size();
+                if matches!(l, MatrixLayout::C { .. }) {
+                    square_transpose(l, a);
+                }
+                let mut info = 0;
+                unsafe {
+                    $tri(uplo.as_ptr(), &n, AsPtr::as_mut_ptr(a), &l.lda(), &mut info);
+                }
+                info.as_lapack_result()?;
+                if matches!(l, MatrixLayout::C { .. }) {
+                    square_transpose(l, a);
+                }
+                Ok(())
+            }
+
+            fn solve_cholesky(
+                l: MatrixLayout,
+                mut uplo: UPLO,
+                a: &[Self],
+                b: &mut [Self],
+            ) -> Result<()> {
+                let (n, _) = l.size();
+                let nrhs = 1;
+                let mut info = 0;
+                if matches!(l, MatrixLayout::C { .. }) {
+                    uplo = uplo.t();
+                    for val in b.iter_mut() {
+                        *val = val.conj();
+                    }
+                }
+                unsafe {
+                    $trs(
+                        uplo.as_ptr(),
+                        &n,
+                        &nrhs,
+                        AsPtr::as_ptr(a),
+                        &l.lda(),
+                        AsPtr::as_mut_ptr(b),
+                        &n,
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+                if matches!(l, MatrixLayout::C { .. }) {
+                    for val in b.iter_mut() {
+                        *val = val.conj();
+                    }
+                }
+                Ok(())
+            }
+        }
+    };
+} // end macro_rules
+
+impl_cholesky!(
+    f64,
+    lapack_sys::dpotrf_,
+    lapack_sys::dpotri_,
+    lapack_sys::dpotrs_
+);
+impl_cholesky!(
+    f32,
+    lapack_sys::spotrf_,
+    lapack_sys::spotri_,
+    lapack_sys::spotrs_
+);
+impl_cholesky!(
+    c64,
+    lapack_sys::zpotrf_,
+    lapack_sys::zpotri_,
+    lapack_sys::zpotrs_
+);
+impl_cholesky!(
+    c32,
+    lapack_sys::cpotrf_,
+    lapack_sys::cpotri_,
+    lapack_sys::cpotrs_
+);
+
+
+ \ No newline at end of file diff --git a/src/lax/eig.rs.html b/src/lax/eig.rs.html new file mode 100644 index 00000000..cdb285e7 --- /dev/null +++ b/src/lax/eig.rs.html @@ -0,0 +1,574 @@ +eig.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+
//! Eigenvalue decomposition for general matrices
+
+use crate::{error::*, layout::MatrixLayout, *};
+use cauchy::*;
+use num_traits::{ToPrimitive, Zero};
+
+/// Wraps `*geev` for general matrices
+pub trait Eig_: Scalar {
+    /// Calculate Right eigenvalue
+    fn eig(
+        calc_v: bool,
+        l: MatrixLayout,
+        a: &mut [Self],
+    ) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)>;
+}
+
+macro_rules! impl_eig_complex {
+    ($scalar:ty, $ev:path) => {
+        impl Eig_ for $scalar {
+            fn eig(
+                calc_v: bool,
+                l: MatrixLayout,
+                a: &mut [Self],
+            ) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)> {
+                let (n, _) = l.size();
+                // LAPACK assumes a column-major input. A row-major input can
+                // be interpreted as the transpose of a column-major input. So,
+                // for row-major inputs, we we want to solve the following,
+                // given the column-major input `A`:
+                //
+                //   A^T V = V Λ ⟺ V^T A = Λ V^T ⟺ conj(V)^H A = Λ conj(V)^H
+                //
+                // So, in this case, the right eigenvectors are the conjugates
+                // of the left eigenvectors computed with `A`, and the
+                // eigenvalues are the eigenvalues computed with `A`.
+                let (jobvl, jobvr) = if calc_v {
+                    match l {
+                        MatrixLayout::C { .. } => (EigenVectorFlag::Calc, EigenVectorFlag::Not),
+                        MatrixLayout::F { .. } => (EigenVectorFlag::Not, EigenVectorFlag::Calc),
+                    }
+                } else {
+                    (EigenVectorFlag::Not, EigenVectorFlag::Not)
+                };
+                let mut eigs: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(n as usize) };
+                let mut rwork: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(2 * n as usize) };
+
+                let mut vl: Option<Vec<MaybeUninit<Self>>> =
+                    jobvl.then(|| unsafe { vec_uninit((n * n) as usize) });
+                let mut vr: Option<Vec<MaybeUninit<Self>>> =
+                    jobvr.then(|| unsafe { vec_uninit((n * n) as usize) });
+
+                // calc work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    $ev(
+                        jobvl.as_ptr(),
+                        jobvr.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut eigs),
+                        AsPtr::as_mut_ptr(vl.as_mut().map(|v| v.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(vr.as_mut().map(|v| v.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        AsPtr::as_mut_ptr(&mut rwork),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                // actal ev
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                let lwork = lwork as i32;
+                unsafe {
+                    $ev(
+                        jobvl.as_ptr(),
+                        jobvr.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut eigs),
+                        AsPtr::as_mut_ptr(vl.as_mut().map(|v| v.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(vr.as_mut().map(|v| v.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut work),
+                        &lwork,
+                        AsPtr::as_mut_ptr(&mut rwork),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                let eigs = unsafe { eigs.assume_init() };
+                let vr = unsafe { vr.map(|v| v.assume_init()) };
+                let mut vl = unsafe { vl.map(|v| v.assume_init()) };
+
+                // Hermite conjugate
+                if jobvl.is_calc() {
+                    for c in vl.as_mut().unwrap().iter_mut() {
+                        c.im = -c.im;
+                    }
+                }
+
+                Ok((eigs, vr.or(vl).unwrap_or(Vec::new())))
+            }
+        }
+    };
+}
+
+impl_eig_complex!(c64, lapack_sys::zgeev_);
+impl_eig_complex!(c32, lapack_sys::cgeev_);
+
+macro_rules! impl_eig_real {
+    ($scalar:ty, $ev:path) => {
+        impl Eig_ for $scalar {
+            fn eig(
+                calc_v: bool,
+                l: MatrixLayout,
+                a: &mut [Self],
+            ) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)> {
+                let (n, _) = l.size();
+                // LAPACK assumes a column-major input. A row-major input can
+                // be interpreted as the transpose of a column-major input. So,
+                // for row-major inputs, we we want to solve the following,
+                // given the column-major input `A`:
+                //
+                //   A^T V = V Λ ⟺ V^T A = Λ V^T ⟺ conj(V)^H A = Λ conj(V)^H
+                //
+                // So, in this case, the right eigenvectors are the conjugates
+                // of the left eigenvectors computed with `A`, and the
+                // eigenvalues are the eigenvalues computed with `A`.
+                //
+                // We could conjugate the eigenvalues instead of the
+                // eigenvectors, but we have to reconstruct the eigenvectors
+                // into new matrices anyway, and by not modifying the
+                // eigenvalues, we preserve the nice ordering specified by
+                // `sgeev`/`dgeev`.
+                let (jobvl, jobvr) = if calc_v {
+                    match l {
+                        MatrixLayout::C { .. } => (EigenVectorFlag::Calc, EigenVectorFlag::Not),
+                        MatrixLayout::F { .. } => (EigenVectorFlag::Not, EigenVectorFlag::Calc),
+                    }
+                } else {
+                    (EigenVectorFlag::Not, EigenVectorFlag::Not)
+                };
+                let mut eig_re: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(n as usize) };
+                let mut eig_im: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(n as usize) };
+
+                let mut vl: Option<Vec<MaybeUninit<Self>>> =
+                    jobvl.then(|| unsafe { vec_uninit((n * n) as usize) });
+                let mut vr: Option<Vec<MaybeUninit<Self>>> =
+                    jobvr.then(|| unsafe { vec_uninit((n * n) as usize) });
+
+                // calc work size
+                let mut info = 0;
+                let mut work_size: [Self; 1] = [0.0];
+                unsafe {
+                    $ev(
+                        jobvl.as_ptr(),
+                        jobvr.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut eig_re),
+                        AsPtr::as_mut_ptr(&mut eig_im),
+                        AsPtr::as_mut_ptr(vl.as_mut().map(|v| v.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(vr.as_mut().map(|v| v.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                // actual ev
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                let lwork = lwork as i32;
+                unsafe {
+                    $ev(
+                        jobvl.as_ptr(),
+                        jobvr.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut eig_re),
+                        AsPtr::as_mut_ptr(&mut eig_im),
+                        AsPtr::as_mut_ptr(vl.as_mut().map(|v| v.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(vr.as_mut().map(|v| v.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut work),
+                        &lwork,
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                let eig_re = unsafe { eig_re.assume_init() };
+                let eig_im = unsafe { eig_im.assume_init() };
+                let vl = unsafe { vl.map(|v| v.assume_init()) };
+                let vr = unsafe { vr.map(|v| v.assume_init()) };
+
+                // reconstruct eigenvalues
+                let eigs: Vec<Self::Complex> = eig_re
+                    .iter()
+                    .zip(eig_im.iter())
+                    .map(|(&re, &im)| Self::complex(re, im))
+                    .collect();
+
+                if !calc_v {
+                    return Ok((eigs, Vec::new()));
+                }
+
+                // Reconstruct eigenvectors into complex-array
+                // --------------------------------------------
+                //
+                // From LAPACK API https://software.intel.com/en-us/node/469230
+                //
+                // - If the j-th eigenvalue is real,
+                //   - v(j) = VR(:,j), the j-th column of VR.
+                //
+                // - If the j-th and (j+1)-st eigenvalues form a complex conjugate pair,
+                //   - v(j)   = VR(:,j) + i*VR(:,j+1)
+                //   - v(j+1) = VR(:,j) - i*VR(:,j+1).
+                //
+                // In the C-layout case, we need the conjugates of the left
+                // eigenvectors, so the signs should be reversed.
+
+                let n = n as usize;
+                let v = vr.or(vl).unwrap();
+                let mut eigvecs: Vec<MaybeUninit<Self::Complex>> = unsafe { vec_uninit(n * n) };
+                let mut col = 0;
+                while col < n {
+                    if eig_im[col] == 0. {
+                        // The corresponding eigenvalue is real.
+                        for row in 0..n {
+                            let re = v[row + col * n];
+                            eigvecs[row + col * n].write(Self::complex(re, 0.));
+                        }
+                        col += 1;
+                    } else {
+                        // This is a complex conjugate pair.
+                        assert!(col + 1 < n);
+                        for row in 0..n {
+                            let re = v[row + col * n];
+                            let mut im = v[row + (col + 1) * n];
+                            if jobvl.is_calc() {
+                                im = -im;
+                            }
+                            eigvecs[row + col * n].write(Self::complex(re, im));
+                            eigvecs[row + (col + 1) * n].write(Self::complex(re, -im));
+                        }
+                        col += 2;
+                    }
+                }
+                let eigvecs = unsafe { eigvecs.assume_init() };
+
+                Ok((eigs, eigvecs))
+            }
+        }
+    };
+}
+
+impl_eig_real!(f64, lapack_sys::dgeev_);
+impl_eig_real!(f32, lapack_sys::sgeev_);
+
+
+ \ No newline at end of file diff --git a/src/lax/eigh.rs.html b/src/lax/eigh.rs.html new file mode 100644 index 00000000..0999e763 --- /dev/null +++ b/src/lax/eigh.rs.html @@ -0,0 +1,354 @@ +eigh.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+
//! Eigenvalue decomposition for Symmetric/Hermite matrices
+
+use super::*;
+use crate::{error::*, layout::MatrixLayout};
+use cauchy::*;
+use num_traits::{ToPrimitive, Zero};
+
+pub trait Eigh_: Scalar {
+    /// Wraps `*syev` for real and `*heev` for complex
+    fn eigh(
+        calc_eigenvec: bool,
+        layout: MatrixLayout,
+        uplo: UPLO,
+        a: &mut [Self],
+    ) -> Result<Vec<Self::Real>>;
+
+    /// Wraps `*sygv` for real and `*hegv` for complex
+    fn eigh_generalized(
+        calc_eigenvec: bool,
+        layout: MatrixLayout,
+        uplo: UPLO,
+        a: &mut [Self],
+        b: &mut [Self],
+    ) -> Result<Vec<Self::Real>>;
+}
+
+macro_rules! impl_eigh {
+    (@real, $scalar:ty, $ev:path, $evg:path) => {
+        impl_eigh!(@body, $scalar, $ev, $evg, );
+    };
+    (@complex, $scalar:ty, $ev:path, $evg:path) => {
+        impl_eigh!(@body, $scalar, $ev, $evg, rwork);
+    };
+    (@body, $scalar:ty, $ev:path, $evg:path, $($rwork_ident:ident),*) => {
+        impl Eigh_ for $scalar {
+            fn eigh(
+                calc_v: bool,
+                layout: MatrixLayout,
+                uplo: UPLO,
+                a: &mut [Self],
+            ) -> Result<Vec<Self::Real>> {
+                assert_eq!(layout.len(), layout.lda());
+                let n = layout.len();
+                let jobz = if calc_v { EigenVectorFlag::Calc } else { EigenVectorFlag::Not };
+                let mut eigs: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(n as usize) };
+
+                $(
+                let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(3 * n as usize - 2 as usize) };
+                )*
+
+                // calc work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    $ev(
+                        jobz.as_ptr() ,
+                        uplo.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut eigs),
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        $(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                // actual ev
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                let lwork = lwork as i32;
+                unsafe {
+                    $ev(
+                        jobz.as_ptr(),
+                        uplo.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut eigs),
+                        AsPtr::as_mut_ptr(&mut work),
+                        &lwork,
+                        $(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                let eigs = unsafe { eigs.assume_init() };
+                Ok(eigs)
+            }
+
+            fn eigh_generalized(
+                calc_v: bool,
+                layout: MatrixLayout,
+                uplo: UPLO,
+                a: &mut [Self],
+                b: &mut [Self],
+            ) -> Result<Vec<Self::Real>> {
+                assert_eq!(layout.len(), layout.lda());
+                let n = layout.len();
+                let jobz = if calc_v { EigenVectorFlag::Calc } else { EigenVectorFlag::Not };
+                let mut eigs: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(n as usize) };
+
+                $(
+                let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(3 * n as usize - 2) };
+                )*
+
+                // calc work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    $evg(
+                        &1, // ITYPE A*x = (lambda)*B*x
+                        jobz.as_ptr(),
+                        uplo.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &n,
+                        AsPtr::as_mut_ptr(b),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut eigs),
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        $(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                // actual evg
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                let lwork = lwork as i32;
+                unsafe {
+                    $evg(
+                        &1, // ITYPE A*x = (lambda)*B*x
+                        jobz.as_ptr(),
+                        uplo.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &n,
+                        AsPtr::as_mut_ptr(b),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut eigs),
+                        AsPtr::as_mut_ptr(&mut work),
+                        &lwork,
+                        $(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+                let eigs = unsafe { eigs.assume_init() };
+                Ok(eigs)
+            }
+        }
+    };
+} // impl_eigh!
+
+impl_eigh!(@real, f64, lapack_sys::dsyev_, lapack_sys::dsygv_);
+impl_eigh!(@real, f32, lapack_sys::ssyev_, lapack_sys::ssygv_);
+impl_eigh!(@complex, c64, lapack_sys::zheev_, lapack_sys::zhegv_);
+impl_eigh!(@complex, c32, lapack_sys::cheev_, lapack_sys::chegv_);
+
+
+ \ No newline at end of file diff --git a/src/lax/error.rs.html b/src/lax/error.rs.html new file mode 100644 index 00000000..811d420d --- /dev/null +++ b/src/lax/error.rs.html @@ -0,0 +1,102 @@ +error.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+
use thiserror::Error;
+
+pub type Result<T> = ::std::result::Result<T, Error>;
+
+#[derive(Error, Debug)]
+pub enum Error {
+    #[error(
+        "Invalid value for LAPACK subroutine {}-th argument",
+        -return_code
+    )]
+    LapackInvalidValue { return_code: i32 },
+
+    #[error(
+        "Computational failure in LAPACK subroutine: return_code = {}",
+        return_code
+    )]
+    LapackComputationalFailure { return_code: i32 },
+
+    /// Strides of the array is not supported
+    #[error("Invalid shape")]
+    InvalidShape,
+}
+
+pub trait AsLapackResult {
+    fn as_lapack_result(self) -> Result<()>;
+}
+
+impl AsLapackResult for i32 {
+    fn as_lapack_result(self) -> Result<()> {
+        if self > 0 {
+            return Err(Error::LapackComputationalFailure { return_code: self });
+        }
+        if self < 0 {
+            return Err(Error::LapackInvalidValue { return_code: self });
+        }
+        Ok(())
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/lax/layout.rs.html b/src/lax/layout.rs.html new file mode 100644 index 00000000..9ba98fcd --- /dev/null +++ b/src/lax/layout.rs.html @@ -0,0 +1,586 @@ +layout.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+
//! Memory layout of matrices
+//!
+//! Different from ndarray format which consists of shape and strides,
+//! matrix format in LAPACK consists of row or column size and leading dimension.
+//!
+//! ndarray format and stride
+//! --------------------------
+//!
+//! Let us consider 3-dimensional array for explaining ndarray structure.
+//! The address of `(x,y,z)`-element in ndarray satisfies following relation:
+//!
+//! ```text
+//! shape = [Nx, Ny, Nz]
+//!     where Nx > 0, Ny > 0, Nz > 0
+//! stride = [Sx, Sy, Sz]
+//!
+//! &data[(x, y, z)] = &data[(0, 0, 0)] + Sx*x + Sy*y + Sz*z
+//!     for x < Nx, y < Ny, z < Nz
+//! ```
+//!
+//! The array is called
+//!
+//! - C-continuous if `[Sx, Sy, Sz] = [Nz*Ny, Nz, 1]`
+//! - F(Fortran)-continuous if `[Sx, Sy, Sz] = [1, Nx, Nx*Ny]`
+//!
+//! Strides of ndarray `[Sx, Sy, Sz]` take arbitrary value,
+//! e.g. it can be non-ordered `Sy > Sx > Sz`, or can be negative `Sx < 0`.
+//! If the minimum of `[Sx, Sy, Sz]` equals to `1`,
+//! the value of elements fills `data` memory region and called "continuous".
+//! Non-continuous ndarray is useful to get sub-array without copying data.
+//!
+//! Matrix layout for LAPACK
+//! -------------------------
+//!
+//! LAPACK interface focuses on the linear algebra operations for F-continuous 2-dimensional array.
+//! Under this restriction, stride becomes far simpler; we only have to consider the case `[1, S]`
+//! This `S` for a matrix `A` is called "leading dimension of the array A" in LAPACK document, and denoted by `lda`.
+//!
+
+use super::*;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum MatrixLayout {
+    C { row: i32, lda: i32 },
+    F { col: i32, lda: i32 },
+}
+
+impl MatrixLayout {
+    pub fn size(&self) -> (i32, i32) {
+        match *self {
+            MatrixLayout::C { row, lda } => (row, lda),
+            MatrixLayout::F { col, lda } => (lda, col),
+        }
+    }
+
+    pub fn resized(&self, row: i32, col: i32) -> MatrixLayout {
+        match *self {
+            MatrixLayout::C { .. } => MatrixLayout::C { row, lda: col },
+            MatrixLayout::F { .. } => MatrixLayout::F { col, lda: row },
+        }
+    }
+
+    pub fn lda(&self) -> i32 {
+        std::cmp::max(
+            1,
+            match *self {
+                MatrixLayout::C { lda, .. } | MatrixLayout::F { lda, .. } => lda,
+            },
+        )
+    }
+
+    pub fn len(&self) -> i32 {
+        match *self {
+            MatrixLayout::C { row, .. } => row,
+            MatrixLayout::F { col, .. } => col,
+        }
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    pub fn same_order(&self, other: &MatrixLayout) -> bool {
+        match (self, other) {
+            (MatrixLayout::C { .. }, MatrixLayout::C { .. }) => true,
+            (MatrixLayout::F { .. }, MatrixLayout::F { .. }) => true,
+            _ => false,
+        }
+    }
+
+    pub fn toggle_order(&self) -> Self {
+        match *self {
+            MatrixLayout::C { row, lda } => MatrixLayout::F { lda: row, col: lda },
+            MatrixLayout::F { col, lda } => MatrixLayout::C { row: lda, lda: col },
+        }
+    }
+
+    /// Transpose without changing memory representation
+    ///
+    /// C-contigious row=2, lda=3
+    ///
+    /// ```text
+    /// [[1, 2, 3]
+    ///  [4, 5, 6]]
+    /// ```
+    ///
+    /// and F-contigious col=2, lda=3
+    ///
+    /// ```text
+    /// [[1, 4]
+    ///  [2, 5]
+    ///  [3, 6]]
+    /// ```
+    ///
+    /// have same memory representation `[1, 2, 3, 4, 5, 6]`, and this toggles them.
+    ///
+    /// ```
+    /// # use lax::layout::*;
+    /// let layout = MatrixLayout::C { row: 2, lda: 3 };
+    /// assert_eq!(layout.t(), MatrixLayout::F { col: 2, lda: 3 });
+    /// ```
+    pub fn t(&self) -> Self {
+        match *self {
+            MatrixLayout::C { row, lda } => MatrixLayout::F { col: row, lda },
+            MatrixLayout::F { col, lda } => MatrixLayout::C { row: col, lda },
+        }
+    }
+}
+
+/// In-place transpose of a square matrix by keeping F/C layout
+///
+/// Transpose for C-continuous array
+///
+/// ```rust
+/// # use lax::layout::*;
+/// let layout = MatrixLayout::C { row: 2, lda: 2 };
+/// let mut a = vec![1., 2., 3., 4.];
+/// square_transpose(layout, &mut a);
+/// assert_eq!(a, &[1., 3., 2., 4.]);
+/// ```
+///
+/// Transpose for F-continuous array
+///
+/// ```rust
+/// # use lax::layout::*;
+/// let layout = MatrixLayout::F { col: 2, lda: 2 };
+/// let mut a = vec![1., 3., 2., 4.];
+/// square_transpose(layout, &mut a);
+/// assert_eq!(a, &[1., 2., 3., 4.]);
+/// ```
+///
+/// Panics
+/// ------
+/// - If size of `a` and `layout` size mismatch
+///
+pub fn square_transpose<T: Copy>(layout: MatrixLayout, a: &mut [T]) {
+    let (m, n) = layout.size();
+    let n = n as usize;
+    let m = m as usize;
+    assert_eq!(a.len(), n * m);
+    for i in 0..m {
+        for j in (i + 1)..n {
+            let a_ij = a[i * n + j];
+            let a_ji = a[j * m + i];
+            a[i * n + j] = a_ji;
+            a[j * m + i] = a_ij;
+        }
+    }
+}
+
+/// Out-place transpose for general matrix
+///
+/// Examples
+/// ---------
+///
+/// ```rust
+/// # use lax::layout::*;
+/// let layout = MatrixLayout::C { row: 2, lda: 3 };
+/// let a = vec![1., 2., 3., 4., 5., 6.];
+/// let (l, b) = transpose(layout, &a);
+/// assert_eq!(l, MatrixLayout::F { col: 3, lda: 2 });
+/// assert_eq!(b, &[1., 4., 2., 5., 3., 6.]);
+/// ```
+///
+/// ```rust
+/// # use lax::layout::*;
+/// let layout = MatrixLayout::F { col: 2, lda: 3 };
+/// let a = vec![1., 2., 3., 4., 5., 6.];
+/// let (l, b) = transpose(layout, &a);
+/// assert_eq!(l, MatrixLayout::C { row: 3, lda: 2 });
+/// assert_eq!(b, &[1., 4., 2., 5., 3., 6.]);
+/// ```
+///
+/// Panics
+/// ------
+/// - If input array size and `layout` size mismatch
+///
+pub fn transpose<T: Copy>(layout: MatrixLayout, input: &[T]) -> (MatrixLayout, Vec<T>) {
+    let (m, n) = layout.size();
+    let transposed = layout.resized(n, m).t();
+    let m = m as usize;
+    let n = n as usize;
+    assert_eq!(input.len(), m * n);
+
+    let mut out: Vec<MaybeUninit<T>> = unsafe { vec_uninit(m * n) };
+
+    match layout {
+        MatrixLayout::C { .. } => {
+            for i in 0..m {
+                for j in 0..n {
+                    out[j * m + i].write(input[i * n + j]);
+                }
+            }
+        }
+        MatrixLayout::F { .. } => {
+            for i in 0..m {
+                for j in 0..n {
+                    out[i * n + j].write(input[j * m + i]);
+                }
+            }
+        }
+    }
+    (transposed, unsafe { out.assume_init() })
+}
+
+/// Out-place transpose for general matrix
+///
+/// Examples
+/// ---------
+///
+/// ```rust
+/// # use lax::layout::*;
+/// let layout = MatrixLayout::C { row: 2, lda: 3 };
+/// let a = vec![1., 2., 3., 4., 5., 6.];
+/// let mut b = vec![0.0; a.len()];
+/// let l = transpose_over(layout, &a, &mut b);
+/// assert_eq!(l, MatrixLayout::F { col: 3, lda: 2 });
+/// assert_eq!(b, &[1., 4., 2., 5., 3., 6.]);
+/// ```
+///
+/// ```rust
+/// # use lax::layout::*;
+/// let layout = MatrixLayout::F { col: 2, lda: 3 };
+/// let a = vec![1., 2., 3., 4., 5., 6.];
+/// let mut b = vec![0.0; a.len()];
+/// let l = transpose_over(layout, &a, &mut b);
+/// assert_eq!(l, MatrixLayout::C { row: 3, lda: 2 });
+/// assert_eq!(b, &[1., 4., 2., 5., 3., 6.]);
+/// ```
+///
+/// Panics
+/// ------
+/// - If input array sizes and `layout` size mismatch
+///
+pub fn transpose_over<T: Copy>(layout: MatrixLayout, from: &[T], to: &mut [T]) -> MatrixLayout {
+    let (m, n) = layout.size();
+    let transposed = layout.resized(n, m).t();
+    let m = m as usize;
+    let n = n as usize;
+    assert_eq!(from.len(), m * n);
+    assert_eq!(to.len(), m * n);
+
+    match layout {
+        MatrixLayout::C { .. } => {
+            for i in 0..m {
+                for j in 0..n {
+                    to[j * m + i] = from[i * n + j];
+                }
+            }
+        }
+        MatrixLayout::F { .. } => {
+            for i in 0..m {
+                for j in 0..n {
+                    to[i * n + j] = from[j * m + i];
+                }
+            }
+        }
+    }
+    transposed
+}
+
+
+ \ No newline at end of file diff --git a/src/lax/least_squares.rs.html b/src/lax/least_squares.rs.html new file mode 100644 index 00000000..b6b02259 --- /dev/null +++ b/src/lax/least_squares.rs.html @@ -0,0 +1,368 @@ +least_squares.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+
//! Least squares
+
+use crate::{error::*, layout::*, *};
+use cauchy::*;
+use num_traits::{ToPrimitive, Zero};
+
+/// Result of LeastSquares
+pub struct LeastSquaresOutput<A: Scalar> {
+    /// singular values
+    pub singular_values: Vec<A::Real>,
+    /// The rank of the input matrix A
+    pub rank: i32,
+}
+
+/// Wraps `*gelsd`
+pub trait LeastSquaresSvdDivideConquer_: Scalar {
+    fn least_squares(
+        a_layout: MatrixLayout,
+        a: &mut [Self],
+        b: &mut [Self],
+    ) -> Result<LeastSquaresOutput<Self>>;
+
+    fn least_squares_nrhs(
+        a_layout: MatrixLayout,
+        a: &mut [Self],
+        b_layout: MatrixLayout,
+        b: &mut [Self],
+    ) -> Result<LeastSquaresOutput<Self>>;
+}
+
+macro_rules! impl_least_squares {
+    (@real, $scalar:ty, $gelsd:path) => {
+        impl_least_squares!(@body, $scalar, $gelsd, );
+    };
+    (@complex, $scalar:ty, $gelsd:path) => {
+        impl_least_squares!(@body, $scalar, $gelsd, rwork);
+    };
+
+    (@body, $scalar:ty, $gelsd:path, $($rwork:ident),*) => {
+        impl LeastSquaresSvdDivideConquer_ for $scalar {
+            fn least_squares(
+                l: MatrixLayout,
+                a: &mut [Self],
+                b: &mut [Self],
+            ) -> Result<LeastSquaresOutput<Self>> {
+                let b_layout = l.resized(b.len() as i32, 1);
+                Self::least_squares_nrhs(l, a, b_layout, b)
+            }
+
+            fn least_squares_nrhs(
+                a_layout: MatrixLayout,
+                a: &mut [Self],
+                b_layout: MatrixLayout,
+                b: &mut [Self],
+            ) -> Result<LeastSquaresOutput<Self>> {
+                // Minimize |b - Ax|_2
+                //
+                // where
+                //   A : (m, n)
+                //   b : (max(m, n), nrhs)  // `b` has to store `x` on exit
+                //   x : (n, nrhs)
+                let (m, n) = a_layout.size();
+                let (m_, nrhs) = b_layout.size();
+                let k = m.min(n);
+                assert!(m_ >= m);
+
+                // Transpose if a is C-continuous
+                let mut a_t = None;
+                let a_layout = match a_layout {
+                    MatrixLayout::C { .. } => {
+                        let (layout, t) = transpose(a_layout, a);
+                        a_t = Some(t);
+                        layout
+                    }
+                    MatrixLayout::F { .. } => a_layout,
+                };
+
+                // Transpose if b is C-continuous
+                let mut b_t = None;
+                let b_layout = match b_layout {
+                    MatrixLayout::C { .. } => {
+                        let (layout, t) = transpose(b_layout, b);
+                        b_t = Some(t);
+                        layout
+                    }
+                    MatrixLayout::F { .. } => b_layout,
+                };
+
+                let rcond: Self::Real = -1.;
+                let mut singular_values: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit( k as usize) };
+                let mut rank: i32 = 0;
+
+                // eval work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                let mut iwork_size = [0];
+                $(
+                let mut $rwork = [Self::Real::zero()];
+                )*
+                unsafe {
+                    $gelsd(
+                        &m,
+                        &n,
+                        &nrhs,
+                        AsPtr::as_mut_ptr(a_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(a)),
+                        &a_layout.lda(),
+                        AsPtr::as_mut_ptr(b_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(b)),
+                        &b_layout.lda(),
+                        AsPtr::as_mut_ptr(&mut singular_values),
+                        &rcond,
+                        &mut rank,
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        $(AsPtr::as_mut_ptr(&mut $rwork),)*
+                        iwork_size.as_mut_ptr(),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                // calc
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                let liwork = iwork_size[0].to_usize().unwrap();
+                let mut iwork: Vec<MaybeUninit<i32>> = unsafe { vec_uninit(liwork) };
+                $(
+                let lrwork = $rwork[0].to_usize().unwrap();
+                let mut $rwork: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(lrwork) };
+                )*
+                unsafe {
+                    $gelsd(
+                        &m,
+                        &n,
+                        &nrhs,
+                        AsPtr::as_mut_ptr(a_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(a)),
+                        &a_layout.lda(),
+                        AsPtr::as_mut_ptr(b_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(b)),
+                        &b_layout.lda(),
+                        AsPtr::as_mut_ptr(&mut singular_values),
+                        &rcond,
+                        &mut rank,
+                        AsPtr::as_mut_ptr(&mut work),
+                        &(lwork as i32),
+                        $(AsPtr::as_mut_ptr(&mut $rwork),)*
+                        AsPtr::as_mut_ptr(&mut iwork),
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                let singular_values = unsafe { singular_values.assume_init() };
+
+                // Skip a_t -> a transpose because A has been destroyed
+                // Re-transpose b
+                if let Some(b_t) = b_t {
+                    transpose_over(b_layout, &b_t, b);
+                }
+
+                Ok(LeastSquaresOutput {
+                    singular_values,
+                    rank,
+                })
+            }
+        }
+    };
+}
+
+impl_least_squares!(@real, f64, lapack_sys::dgelsd_);
+impl_least_squares!(@real, f32, lapack_sys::sgelsd_);
+impl_least_squares!(@complex, c64, lapack_sys::zgelsd_);
+impl_least_squares!(@complex, c32, lapack_sys::cgelsd_);
+
+
+ \ No newline at end of file diff --git a/src/lax/lib.rs.html b/src/lax/lib.rs.html new file mode 100644 index 00000000..256204a1 --- /dev/null +++ b/src/lax/lib.rs.html @@ -0,0 +1,578 @@ +lib.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+
//! Linear Algebra eXtension (LAX)
+//! ===============================
+//!
+//! ndarray-free safe Rust wrapper for LAPACK FFI
+//!
+//! Linear equation, Inverse matrix, Condition number
+//! --------------------------------------------------
+//!
+//! As the property of $A$, several types of triangular factorization are used:
+//!
+//! - LU-decomposition for general matrix
+//!   - $PA = LU$, where $L$ is lower matrix, $U$ is upper matrix, and $P$ is permutation matrix
+//! - Bunch-Kaufman diagonal pivoting method for nonpositive-definite Hermitian matrix
+//!   - $A = U D U^\dagger$, where $U$ is upper matrix,
+//!     $D$ is Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks.
+//!
+//! | matrix type                     | Triangler factorization (TRF) | Solve (TRS) | Inverse matrix (TRI) | Reciprocal condition number (CON) |
+//! |:--------------------------------|:------------------------------|:------------|:---------------------|:----------------------------------|
+//! | General (GE)                    | [lu]                          | [solve]     | [inv]                | [rcond]                           |
+//! | Symmetric (SY) / Hermitian (HE) | [bk]                          | [solveh]    | [invh]               | -                                 |
+//!
+//! [lu]:    solve/trait.Solve_.html#tymethod.lu
+//! [solve]: solve/trait.Solve_.html#tymethod.solve
+//! [inv]:   solve/trait.Solve_.html#tymethod.inv
+//! [rcond]: solve/trait.Solve_.html#tymethod.rcond
+//!
+//! [bk]:     solveh/trait.Solveh_.html#tymethod.bk
+//! [solveh]: solveh/trait.Solveh_.html#tymethod.solveh
+//! [invh]:   solveh/trait.Solveh_.html#tymethod.invh
+//!
+//! Eigenvalue Problem
+//! -------------------
+//!
+//! Solve eigenvalue problem for a matrix $A$
+//!
+//! $$ Av_i = \lambda_i v_i $$
+//!
+//! or generalized eigenvalue problem
+//!
+//! $$ Av_i = \lambda_i B v_i $$
+//!
+//! | matrix type                     | Eigenvalue (EV) | Generalized Eigenvalue Problem (EG) |
+//! |:--------------------------------|:----------------|:------------------------------------|
+//! | General (GE)                    |[eig]            | -                                   |
+//! | Symmetric (SY) / Hermitian (HE) |[eigh]           |[eigh_generalized]                   |
+//!
+//! [eig]:              eig/trait.Eig_.html#tymethod.eig
+//! [eigh]:             eigh/trait.Eigh_.html#tymethod.eigh
+//! [eigh_generalized]: eigh/trait.Eigh_.html#tymethod.eigh_generalized
+//!
+//! Singular Value Decomposition (SVD), Least square problem
+//! ----------------------------------------------------------
+//!
+//! | matrix type  | Singular Value Decomposition (SVD) | SVD with divided-and-conquer (SDD) | Least square problem (LSD) |
+//! |:-------------|:-----------------------------------|:-----------------------------------|:---------------------------|
+//! | General (GE) | [svd]                              | [svddc]                            | [least_squares]            |
+//!
+//! [svd]:   svd/trait.SVD_.html#tymethod.svd
+//! [svddc]: svddck/trait.SVDDC_.html#tymethod.svddc
+//! [least_squares]: least_squares/trait.LeastSquaresSvdDivideConquer_.html#tymethod.least_squares
+
+#[cfg(any(feature = "intel-mkl-system", feature = "intel-mkl-static"))]
+extern crate intel_mkl_src as _src;
+
+#[cfg(any(feature = "openblas-system", feature = "openblas-static"))]
+extern crate openblas_src as _src;
+
+#[cfg(any(feature = "netlib-system", feature = "netlib-static"))]
+extern crate netlib_src as _src;
+
+pub mod error;
+pub mod layout;
+
+mod cholesky;
+mod eig;
+mod eigh;
+mod least_squares;
+mod opnorm;
+mod qr;
+mod rcond;
+mod solve;
+mod solveh;
+mod svd;
+mod svddc;
+mod triangular;
+mod tridiagonal;
+
+pub use self::cholesky::*;
+pub use self::eig::*;
+pub use self::eigh::*;
+pub use self::least_squares::*;
+pub use self::opnorm::*;
+pub use self::qr::*;
+pub use self::rcond::*;
+pub use self::solve::*;
+pub use self::solveh::*;
+pub use self::svd::*;
+pub use self::svddc::*;
+pub use self::triangular::*;
+pub use self::tridiagonal::*;
+
+use cauchy::*;
+use std::mem::MaybeUninit;
+
+pub type Pivot = Vec<i32>;
+
+/// Trait for primitive types which implements LAPACK subroutines
+pub trait Lapack:
+    OperatorNorm_
+    + QR_
+    + SVD_
+    + SVDDC_
+    + Solve_
+    + Solveh_
+    + Cholesky_
+    + Eig_
+    + Eigh_
+    + Triangular_
+    + Tridiagonal_
+    + Rcond_
+    + LeastSquaresSvdDivideConquer_
+{
+}
+
+impl Lapack for f32 {}
+impl Lapack for f64 {}
+impl Lapack for c32 {}
+impl Lapack for c64 {}
+
+/// Helper for getting pointer of slice
+pub(crate) trait AsPtr: Sized {
+    type Elem;
+    fn as_ptr(vec: &[Self]) -> *const Self::Elem;
+    fn as_mut_ptr(vec: &mut [Self]) -> *mut Self::Elem;
+}
+
+macro_rules! impl_as_ptr {
+    ($target:ty, $elem:ty) => {
+        impl AsPtr for $target {
+            type Elem = $elem;
+            fn as_ptr(vec: &[Self]) -> *const Self::Elem {
+                vec.as_ptr() as *const _
+            }
+            fn as_mut_ptr(vec: &mut [Self]) -> *mut Self::Elem {
+                vec.as_mut_ptr() as *mut _
+            }
+        }
+    };
+}
+impl_as_ptr!(i32, i32);
+impl_as_ptr!(f32, f32);
+impl_as_ptr!(f64, f64);
+impl_as_ptr!(c32, lapack_sys::__BindgenComplex<f32>);
+impl_as_ptr!(c64, lapack_sys::__BindgenComplex<f64>);
+impl_as_ptr!(MaybeUninit<i32>, i32);
+impl_as_ptr!(MaybeUninit<f32>, f32);
+impl_as_ptr!(MaybeUninit<f64>, f64);
+impl_as_ptr!(MaybeUninit<c32>, lapack_sys::__BindgenComplex<f32>);
+impl_as_ptr!(MaybeUninit<c64>, lapack_sys::__BindgenComplex<f64>);
+
+pub(crate) trait VecAssumeInit {
+    type Target;
+    unsafe fn assume_init(self) -> Self::Target;
+}
+
+impl<T> VecAssumeInit for Vec<MaybeUninit<T>> {
+    type Target = Vec<T>;
+    unsafe fn assume_init(self) -> Self::Target {
+        // FIXME use Vec::into_raw_parts instead after stablized
+        // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.into_raw_parts
+        let mut me = std::mem::ManuallyDrop::new(self);
+        Vec::from_raw_parts(me.as_mut_ptr() as *mut T, me.len(), me.capacity())
+    }
+}
+
+/// Upper/Lower specification for seveal usages
+#[derive(Debug, Clone, Copy)]
+#[repr(u8)]
+pub enum UPLO {
+    Upper = b'U',
+    Lower = b'L',
+}
+
+impl UPLO {
+    pub fn t(self) -> Self {
+        match self {
+            UPLO::Upper => UPLO::Lower,
+            UPLO::Lower => UPLO::Upper,
+        }
+    }
+
+    /// To use Fortran LAPACK API in lapack-sys crate
+    pub fn as_ptr(&self) -> *const i8 {
+        self as *const UPLO as *const i8
+    }
+}
+
+#[derive(Debug, Clone, Copy)]
+#[repr(u8)]
+pub enum Transpose {
+    No = b'N',
+    Transpose = b'T',
+    Hermite = b'C',
+}
+
+impl Transpose {
+    /// To use Fortran LAPACK API in lapack-sys crate
+    pub fn as_ptr(&self) -> *const i8 {
+        self as *const Transpose as *const i8
+    }
+}
+
+#[derive(Debug, Clone, Copy)]
+#[repr(u8)]
+pub enum NormType {
+    One = b'O',
+    Infinity = b'I',
+    Frobenius = b'F',
+}
+
+impl NormType {
+    pub fn transpose(self) -> Self {
+        match self {
+            NormType::One => NormType::Infinity,
+            NormType::Infinity => NormType::One,
+            NormType::Frobenius => NormType::Frobenius,
+        }
+    }
+
+    /// To use Fortran LAPACK API in lapack-sys crate
+    pub fn as_ptr(&self) -> *const i8 {
+        self as *const NormType as *const i8
+    }
+}
+
+/// Flag for calculating eigenvectors or not
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u8)]
+pub enum EigenVectorFlag {
+    Calc = b'V',
+    Not = b'N',
+}
+
+impl EigenVectorFlag {
+    pub fn is_calc(&self) -> bool {
+        match self {
+            EigenVectorFlag::Calc => true,
+            EigenVectorFlag::Not => false,
+        }
+    }
+
+    pub fn then<T, F: FnOnce() -> T>(&self, f: F) -> Option<T> {
+        if self.is_calc() {
+            Some(f())
+        } else {
+            None
+        }
+    }
+
+    /// To use Fortran LAPACK API in lapack-sys crate
+    pub fn as_ptr(&self) -> *const i8 {
+        self as *const EigenVectorFlag as *const i8
+    }
+}
+
+/// Create a vector without initialization
+///
+/// Safety
+/// ------
+/// - Memory is not initialized. Do not read the memory before write.
+///
+unsafe fn vec_uninit<T: Sized>(n: usize) -> Vec<MaybeUninit<T>> {
+    let mut v = Vec::with_capacity(n);
+    v.set_len(n);
+    v
+}
+
+
+ \ No newline at end of file diff --git a/src/lax/opnorm.rs.html b/src/lax/opnorm.rs.html new file mode 100644 index 00000000..3224a402 --- /dev/null +++ b/src/lax/opnorm.rs.html @@ -0,0 +1,114 @@ +opnorm.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
//! Operator norms of matrices
+
+use super::{AsPtr, NormType};
+use crate::{layout::MatrixLayout, *};
+use cauchy::*;
+
+pub trait OperatorNorm_: Scalar {
+    fn opnorm(t: NormType, l: MatrixLayout, a: &[Self]) -> Self::Real;
+}
+
+macro_rules! impl_opnorm {
+    ($scalar:ty, $lange:path) => {
+        impl OperatorNorm_ for $scalar {
+            fn opnorm(t: NormType, l: MatrixLayout, a: &[Self]) -> Self::Real {
+                let m = l.lda();
+                let n = l.len();
+                let t = match l {
+                    MatrixLayout::F { .. } => t,
+                    MatrixLayout::C { .. } => t.transpose(),
+                };
+                let mut work: Vec<MaybeUninit<Self::Real>> = if matches!(t, NormType::Infinity) {
+                    unsafe { vec_uninit(m as usize) }
+                } else {
+                    Vec::new()
+                };
+                unsafe {
+                    $lange(
+                        t.as_ptr(),
+                        &m,
+                        &n,
+                        AsPtr::as_ptr(a),
+                        &m,
+                        AsPtr::as_mut_ptr(&mut work),
+                    )
+                }
+            }
+        }
+    };
+} // impl_opnorm!
+
+impl_opnorm!(f64, lapack_sys::dlange_);
+impl_opnorm!(f32, lapack_sys::slange_);
+impl_opnorm!(c64, lapack_sys::zlange_);
+impl_opnorm!(c32, lapack_sys::clange_);
+
+
+ \ No newline at end of file diff --git a/src/lax/qr.rs.html b/src/lax/qr.rs.html new file mode 100644 index 00000000..abc6ffed --- /dev/null +++ b/src/lax/qr.rs.html @@ -0,0 +1,440 @@ +qr.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+
//! QR decomposition
+
+use crate::{error::*, layout::MatrixLayout, *};
+use cauchy::*;
+use num_traits::{ToPrimitive, Zero};
+
+pub trait QR_: Sized {
+    /// Execute Householder reflection as the first step of QR-decomposition
+    ///
+    /// For C-continuous array,
+    /// this will call LQ-decomposition of the transposed matrix $ A^T = LQ^T $
+    fn householder(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>>;
+
+    /// Reconstruct Q-matrix from Householder-reflectors
+    fn q(l: MatrixLayout, a: &mut [Self], tau: &[Self]) -> Result<()>;
+
+    /// Execute QR-decomposition at once
+    fn qr(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>>;
+}
+
+macro_rules! impl_qr {
+    ($scalar:ty, $qrf:path, $lqf:path, $gqr:path, $glq:path) => {
+        impl QR_ for $scalar {
+            fn householder(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>> {
+                let m = l.lda();
+                let n = l.len();
+                let k = m.min(n);
+                let mut tau = unsafe { vec_uninit(k as usize) };
+
+                // eval work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    match l {
+                        MatrixLayout::F { .. } => {
+                            $qrf(
+                                &m,
+                                &n,
+                                AsPtr::as_mut_ptr(a),
+                                &m,
+                                AsPtr::as_mut_ptr(&mut tau),
+                                AsPtr::as_mut_ptr(&mut work_size),
+                                &(-1),
+                                &mut info,
+                            );
+                        }
+                        MatrixLayout::C { .. } => {
+                            $lqf(
+                                &m,
+                                &n,
+                                AsPtr::as_mut_ptr(a),
+                                &m,
+                                AsPtr::as_mut_ptr(&mut tau),
+                                AsPtr::as_mut_ptr(&mut work_size),
+                                &(-1),
+                                &mut info,
+                            );
+                        }
+                    }
+                }
+                info.as_lapack_result()?;
+
+                // calc
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                unsafe {
+                    match l {
+                        MatrixLayout::F { .. } => {
+                            $qrf(
+                                &m,
+                                &n,
+                                AsPtr::as_mut_ptr(a),
+                                &m,
+                                AsPtr::as_mut_ptr(&mut tau),
+                                AsPtr::as_mut_ptr(&mut work),
+                                &(lwork as i32),
+                                &mut info,
+                            );
+                        }
+                        MatrixLayout::C { .. } => {
+                            $lqf(
+                                &m,
+                                &n,
+                                AsPtr::as_mut_ptr(a),
+                                &m,
+                                AsPtr::as_mut_ptr(&mut tau),
+                                AsPtr::as_mut_ptr(&mut work),
+                                &(lwork as i32),
+                                &mut info,
+                            );
+                        }
+                    }
+                }
+                info.as_lapack_result()?;
+
+                let tau = unsafe { tau.assume_init() };
+
+                Ok(tau)
+            }
+
+            fn q(l: MatrixLayout, a: &mut [Self], tau: &[Self]) -> Result<()> {
+                let m = l.lda();
+                let n = l.len();
+                let k = m.min(n);
+                assert_eq!(tau.len(), k as usize);
+
+                // eval work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    match l {
+                        MatrixLayout::F { .. } => $gqr(
+                            &m,
+                            &k,
+                            &k,
+                            AsPtr::as_mut_ptr(a),
+                            &m,
+                            AsPtr::as_ptr(&tau),
+                            AsPtr::as_mut_ptr(&mut work_size),
+                            &(-1),
+                            &mut info,
+                        ),
+                        MatrixLayout::C { .. } => $glq(
+                            &k,
+                            &n,
+                            &k,
+                            AsPtr::as_mut_ptr(a),
+                            &m,
+                            AsPtr::as_ptr(&tau),
+                            AsPtr::as_mut_ptr(&mut work_size),
+                            &(-1),
+                            &mut info,
+                        ),
+                    }
+                };
+
+                // calc
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                unsafe {
+                    match l {
+                        MatrixLayout::F { .. } => $gqr(
+                            &m,
+                            &k,
+                            &k,
+                            AsPtr::as_mut_ptr(a),
+                            &m,
+                            AsPtr::as_ptr(&tau),
+                            AsPtr::as_mut_ptr(&mut work),
+                            &(lwork as i32),
+                            &mut info,
+                        ),
+                        MatrixLayout::C { .. } => $glq(
+                            &k,
+                            &n,
+                            &k,
+                            AsPtr::as_mut_ptr(a),
+                            &m,
+                            AsPtr::as_ptr(&tau),
+                            AsPtr::as_mut_ptr(&mut work),
+                            &(lwork as i32),
+                            &mut info,
+                        ),
+                    }
+                }
+                info.as_lapack_result()?;
+                Ok(())
+            }
+
+            fn qr(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>> {
+                let tau = Self::householder(l, a)?;
+                let r = Vec::from(&*a);
+                Self::q(l, a, &tau)?;
+                Ok(r)
+            }
+        }
+    };
+} // endmacro
+
+impl_qr!(
+    f64,
+    lapack_sys::dgeqrf_,
+    lapack_sys::dgelqf_,
+    lapack_sys::dorgqr_,
+    lapack_sys::dorglq_
+);
+impl_qr!(
+    f32,
+    lapack_sys::sgeqrf_,
+    lapack_sys::sgelqf_,
+    lapack_sys::sorgqr_,
+    lapack_sys::sorglq_
+);
+impl_qr!(
+    c64,
+    lapack_sys::zgeqrf_,
+    lapack_sys::zgelqf_,
+    lapack_sys::zungqr_,
+    lapack_sys::zunglq_
+);
+impl_qr!(
+    c32,
+    lapack_sys::cgeqrf_,
+    lapack_sys::cgelqf_,
+    lapack_sys::cungqr_,
+    lapack_sys::cunglq_
+);
+
+
+ \ No newline at end of file diff --git a/src/lax/rcond.rs.html b/src/lax/rcond.rs.html new file mode 100644 index 00000000..b1b15594 --- /dev/null +++ b/src/lax/rcond.rs.html @@ -0,0 +1,196 @@ +rcond.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+
use crate::{error::*, layout::MatrixLayout, *};
+use cauchy::*;
+use num_traits::Zero;
+
+pub trait Rcond_: Scalar + Sized {
+    /// Estimates the the reciprocal of the condition number of the matrix in 1-norm.
+    ///
+    /// `anorm` should be the 1-norm of the matrix `a`.
+    fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real>;
+}
+
+macro_rules! impl_rcond_real {
+    ($scalar:ty, $gecon:path) => {
+        impl Rcond_ for $scalar {
+            fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real> {
+                let (n, _) = l.size();
+                let mut rcond = Self::Real::zero();
+                let mut info = 0;
+
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(4 * n as usize) };
+                let mut iwork: Vec<MaybeUninit<i32>> = unsafe { vec_uninit(n as usize) };
+                let norm_type = match l {
+                    MatrixLayout::C { .. } => NormType::Infinity,
+                    MatrixLayout::F { .. } => NormType::One,
+                };
+                unsafe {
+                    $gecon(
+                        norm_type.as_ptr(),
+                        &n,
+                        AsPtr::as_ptr(a),
+                        &l.lda(),
+                        &anorm,
+                        &mut rcond,
+                        AsPtr::as_mut_ptr(&mut work),
+                        AsPtr::as_mut_ptr(&mut iwork),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                Ok(rcond)
+            }
+        }
+    };
+}
+
+impl_rcond_real!(f32, lapack_sys::sgecon_);
+impl_rcond_real!(f64, lapack_sys::dgecon_);
+
+macro_rules! impl_rcond_complex {
+    ($scalar:ty, $gecon:path) => {
+        impl Rcond_ for $scalar {
+            fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real> {
+                let (n, _) = l.size();
+                let mut rcond = Self::Real::zero();
+                let mut info = 0;
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(2 * n as usize) };
+                let mut rwork: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(2 * n as usize) };
+                let norm_type = match l {
+                    MatrixLayout::C { .. } => NormType::Infinity,
+                    MatrixLayout::F { .. } => NormType::One,
+                };
+                unsafe {
+                    $gecon(
+                        norm_type.as_ptr(),
+                        &n,
+                        AsPtr::as_ptr(a),
+                        &l.lda(),
+                        &anorm,
+                        &mut rcond,
+                        AsPtr::as_mut_ptr(&mut work),
+                        AsPtr::as_mut_ptr(&mut rwork),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                Ok(rcond)
+            }
+        }
+    };
+}
+
+impl_rcond_complex!(c32, lapack_sys::cgecon_);
+impl_rcond_complex!(c64, lapack_sys::zgecon_);
+
+
+ \ No newline at end of file diff --git a/src/lax/solve.rs.html b/src/lax/solve.rs.html new file mode 100644 index 00000000..e36e2d7d --- /dev/null +++ b/src/lax/solve.rs.html @@ -0,0 +1,400 @@ +solve.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+
//! Solve linear problem using LU decomposition
+
+use crate::{error::*, layout::MatrixLayout, *};
+use cauchy::*;
+use num_traits::{ToPrimitive, Zero};
+
+pub trait Solve_: Scalar + Sized {
+    /// Computes the LU factorization of a general `m x n` matrix `a` using
+    /// partial pivoting with row interchanges.
+    ///
+    /// $ PA = LU $
+    ///
+    /// Error
+    /// ------
+    /// - `LapackComputationalFailure { return_code }` when the matrix is singular
+    ///   - Division by zero will occur if it is used to solve a system of equations
+    ///     because `U[(return_code-1, return_code-1)]` is exactly zero.
+    fn lu(l: MatrixLayout, a: &mut [Self]) -> Result<Pivot>;
+
+    fn inv(l: MatrixLayout, a: &mut [Self], p: &Pivot) -> Result<()>;
+
+    fn solve(l: MatrixLayout, t: Transpose, a: &[Self], p: &Pivot, b: &mut [Self]) -> Result<()>;
+}
+
+macro_rules! impl_solve {
+    ($scalar:ty, $getrf:path, $getri:path, $getrs:path) => {
+        impl Solve_ for $scalar {
+            fn lu(l: MatrixLayout, a: &mut [Self]) -> Result<Pivot> {
+                let (row, col) = l.size();
+                assert_eq!(a.len() as i32, row * col);
+                if row == 0 || col == 0 {
+                    // Do nothing for empty matrix
+                    return Ok(Vec::new());
+                }
+                let k = ::std::cmp::min(row, col);
+                let mut ipiv = unsafe { vec_uninit(k as usize) };
+                let mut info = 0;
+                unsafe {
+                    $getrf(
+                        &l.lda(),
+                        &l.len(),
+                        AsPtr::as_mut_ptr(a),
+                        &l.lda(),
+                        AsPtr::as_mut_ptr(&mut ipiv),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+                let ipiv = unsafe { ipiv.assume_init() };
+                Ok(ipiv)
+            }
+
+            fn inv(l: MatrixLayout, a: &mut [Self], ipiv: &Pivot) -> Result<()> {
+                let (n, _) = l.size();
+                if n == 0 {
+                    // Do nothing for empty matrices.
+                    return Ok(());
+                }
+
+                // calc work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    $getri(
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &l.lda(),
+                        ipiv.as_ptr(),
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                // actual
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                unsafe {
+                    $getri(
+                        &l.len(),
+                        AsPtr::as_mut_ptr(a),
+                        &l.lda(),
+                        ipiv.as_ptr(),
+                        AsPtr::as_mut_ptr(&mut work),
+                        &(lwork as i32),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                Ok(())
+            }
+
+            fn solve(
+                l: MatrixLayout,
+                t: Transpose,
+                a: &[Self],
+                ipiv: &Pivot,
+                b: &mut [Self],
+            ) -> Result<()> {
+                // If the array has C layout, then it needs to be handled
+                // specially, since LAPACK expects a Fortran-layout array.
+                // Reinterpreting a C layout array as Fortran layout is
+                // equivalent to transposing it. So, we can handle the "no
+                // transpose" and "transpose" cases by swapping to "transpose"
+                // or "no transpose", respectively. For the "Hermite" case, we
+                // can take advantage of the following:
+                //
+                // ```text
+                // A^H x = b
+                // ⟺ conj(A^T) x = b
+                // ⟺ conj(conj(A^T) x) = conj(b)
+                // ⟺ conj(conj(A^T)) conj(x) = conj(b)
+                // ⟺ A^T conj(x) = conj(b)
+                // ```
+                //
+                // So, we can handle this case by switching to "no transpose"
+                // (which is equivalent to transposing the array since it will
+                // be reinterpreted as Fortran layout) and applying the
+                // elementwise conjugate to `x` and `b`.
+                let (t, conj) = match l {
+                    MatrixLayout::C { .. } => match t {
+                        Transpose::No => (Transpose::Transpose, false),
+                        Transpose::Transpose => (Transpose::No, false),
+                        Transpose::Hermite => (Transpose::No, true),
+                    },
+                    MatrixLayout::F { .. } => (t, false),
+                };
+                let (n, _) = l.size();
+                let nrhs = 1;
+                let ldb = l.lda();
+                let mut info = 0;
+                if conj {
+                    for b_elem in &mut *b {
+                        *b_elem = b_elem.conj();
+                    }
+                }
+                unsafe {
+                    $getrs(
+                        t.as_ptr(),
+                        &n,
+                        &nrhs,
+                        AsPtr::as_ptr(a),
+                        &l.lda(),
+                        ipiv.as_ptr(),
+                        AsPtr::as_mut_ptr(b),
+                        &ldb,
+                        &mut info,
+                    )
+                };
+                if conj {
+                    for b_elem in &mut *b {
+                        *b_elem = b_elem.conj();
+                    }
+                }
+                info.as_lapack_result()?;
+                Ok(())
+            }
+        }
+    };
+} // impl_solve!
+
+impl_solve!(
+    f64,
+    lapack_sys::dgetrf_,
+    lapack_sys::dgetri_,
+    lapack_sys::dgetrs_
+);
+impl_solve!(
+    f32,
+    lapack_sys::sgetrf_,
+    lapack_sys::sgetri_,
+    lapack_sys::sgetrs_
+);
+impl_solve!(
+    c64,
+    lapack_sys::zgetrf_,
+    lapack_sys::zgetri_,
+    lapack_sys::zgetrs_
+);
+impl_solve!(
+    c32,
+    lapack_sys::cgetrf_,
+    lapack_sys::cgetri_,
+    lapack_sys::cgetrs_
+);
+
+
+ \ No newline at end of file diff --git a/src/lax/solveh.rs.html b/src/lax/solveh.rs.html new file mode 100644 index 00000000..a30611d7 --- /dev/null +++ b/src/lax/solveh.rs.html @@ -0,0 +1,298 @@ +solveh.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+
//! Solve symmetric linear problem using the Bunch-Kaufman diagonal pivoting method.
+//!
+//! See also [the manual of dsytrf](http://www.netlib.org/lapack/lapack-3.1.1/html/dsytrf.f.html)
+
+use crate::{error::*, layout::MatrixLayout, *};
+use cauchy::*;
+use num_traits::{ToPrimitive, Zero};
+
+pub trait Solveh_: Sized {
+    /// Bunch-Kaufman: wrapper of `*sytrf` and `*hetrf`
+    fn bk(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<Pivot>;
+    /// Wrapper of `*sytri` and `*hetri`
+    fn invh(l: MatrixLayout, uplo: UPLO, a: &mut [Self], ipiv: &Pivot) -> Result<()>;
+    /// Wrapper of `*sytrs` and `*hetrs`
+    fn solveh(l: MatrixLayout, uplo: UPLO, a: &[Self], ipiv: &Pivot, b: &mut [Self]) -> Result<()>;
+}
+
+macro_rules! impl_solveh {
+    ($scalar:ty, $trf:path, $tri:path, $trs:path) => {
+        impl Solveh_ for $scalar {
+            fn bk(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<Pivot> {
+                let (n, _) = l.size();
+                let mut ipiv = unsafe { vec_uninit(n as usize) };
+                if n == 0 {
+                    return Ok(Vec::new());
+                }
+
+                // calc work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    $trf(
+                        uplo.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &l.lda(),
+                        AsPtr::as_mut_ptr(&mut ipiv),
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+
+                // actual
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
+                unsafe {
+                    $trf(
+                        uplo.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &l.lda(),
+                        AsPtr::as_mut_ptr(&mut ipiv),
+                        AsPtr::as_mut_ptr(&mut work),
+                        &(lwork as i32),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+                let ipiv = unsafe { ipiv.assume_init() };
+                Ok(ipiv)
+            }
+
+            fn invh(l: MatrixLayout, uplo: UPLO, a: &mut [Self], ipiv: &Pivot) -> Result<()> {
+                let (n, _) = l.size();
+                let mut info = 0;
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(n as usize) };
+                unsafe {
+                    $tri(
+                        uplo.as_ptr(),
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &l.lda(),
+                        ipiv.as_ptr(),
+                        AsPtr::as_mut_ptr(&mut work),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+                Ok(())
+            }
+
+            fn solveh(
+                l: MatrixLayout,
+                uplo: UPLO,
+                a: &[Self],
+                ipiv: &Pivot,
+                b: &mut [Self],
+            ) -> Result<()> {
+                let (n, _) = l.size();
+                let mut info = 0;
+                unsafe {
+                    $trs(
+                        uplo.as_ptr(),
+                        &n,
+                        &1,
+                        AsPtr::as_ptr(a),
+                        &l.lda(),
+                        ipiv.as_ptr(),
+                        AsPtr::as_mut_ptr(b),
+                        &n,
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+                Ok(())
+            }
+        }
+    };
+} // impl_solveh!
+
+impl_solveh!(
+    f64,
+    lapack_sys::dsytrf_,
+    lapack_sys::dsytri_,
+    lapack_sys::dsytrs_
+);
+impl_solveh!(
+    f32,
+    lapack_sys::ssytrf_,
+    lapack_sys::ssytri_,
+    lapack_sys::ssytrs_
+);
+impl_solveh!(
+    c64,
+    lapack_sys::zhetrf_,
+    lapack_sys::zhetri_,
+    lapack_sys::zhetrs_
+);
+impl_solveh!(
+    c32,
+    lapack_sys::chetrf_,
+    lapack_sys::chetri_,
+    lapack_sys::chetrs_
+);
+
+
+ \ No newline at end of file diff --git a/src/lax/svd.rs.html b/src/lax/svd.rs.html new file mode 100644 index 00000000..5cfcdec9 --- /dev/null +++ b/src/lax/svd.rs.html @@ -0,0 +1,324 @@ +svd.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+
//! Singular-value decomposition
+
+use crate::{error::*, layout::MatrixLayout, *};
+use cauchy::*;
+use num_traits::{ToPrimitive, Zero};
+
+#[repr(u8)]
+#[derive(Debug, Copy, Clone)]
+enum FlagSVD {
+    All = b'A',
+    // OverWrite = b'O',
+    // Separately = b'S',
+    No = b'N',
+}
+
+impl FlagSVD {
+    fn from_bool(calc_uv: bool) -> Self {
+        if calc_uv {
+            FlagSVD::All
+        } else {
+            FlagSVD::No
+        }
+    }
+
+    fn as_ptr(&self) -> *const i8 {
+        self as *const FlagSVD as *const i8
+    }
+}
+
+/// Result of SVD
+pub struct SVDOutput<A: Scalar> {
+    /// diagonal values
+    pub s: Vec<A::Real>,
+    /// Unitary matrix for destination space
+    pub u: Option<Vec<A>>,
+    /// Unitary matrix for departure space
+    pub vt: Option<Vec<A>>,
+}
+
+/// Wraps `*gesvd`
+pub trait SVD_: Scalar {
+    /// Calculate singular value decomposition $ A = U \Sigma V^T $
+    fn svd(l: MatrixLayout, calc_u: bool, calc_vt: bool, a: &mut [Self])
+        -> Result<SVDOutput<Self>>;
+}
+
+macro_rules! impl_svd {
+    (@real, $scalar:ty, $gesvd:path) => {
+        impl_svd!(@body, $scalar, $gesvd, );
+    };
+    (@complex, $scalar:ty, $gesvd:path) => {
+        impl_svd!(@body, $scalar, $gesvd, rwork);
+    };
+    (@body, $scalar:ty, $gesvd:path, $($rwork_ident:ident),*) => {
+        impl SVD_ for $scalar {
+            fn svd(l: MatrixLayout, calc_u: bool, calc_vt: bool, a: &mut [Self],) -> Result<SVDOutput<Self>> {
+                let ju = match l {
+                    MatrixLayout::F { .. } => FlagSVD::from_bool(calc_u),
+                    MatrixLayout::C { .. } => FlagSVD::from_bool(calc_vt),
+                };
+                let jvt = match l {
+                    MatrixLayout::F { .. } => FlagSVD::from_bool(calc_vt),
+                    MatrixLayout::C { .. } => FlagSVD::from_bool(calc_u),
+                };
+
+                let m = l.lda();
+                let mut u = match ju {
+                    FlagSVD::All => Some(unsafe { vec_uninit( (m * m) as usize) }),
+                    FlagSVD::No => None,
+                };
+
+                let n = l.len();
+                let mut vt = match jvt {
+                    FlagSVD::All => Some(unsafe { vec_uninit( (n * n) as usize) }),
+                    FlagSVD::No => None,
+                };
+
+                let k = std::cmp::min(m, n);
+                let mut s = unsafe { vec_uninit( k as usize) };
+
+                $(
+                let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit( 5 * k as usize) };
+                )*
+
+                // eval work size
+                let mut info = 0;
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    $gesvd(
+                        ju.as_ptr(),
+                        jvt.as_ptr(),
+                        &m,
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &m,
+                        AsPtr::as_mut_ptr(&mut s),
+                        AsPtr::as_mut_ptr(u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])),
+                        &m,
+                        AsPtr::as_mut_ptr(vt.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        $(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                // calc
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit( lwork) };
+                unsafe {
+                    $gesvd(
+                        ju.as_ptr(),
+                        jvt.as_ptr() ,
+                        &m,
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &m,
+                        AsPtr::as_mut_ptr(&mut s),
+                        AsPtr::as_mut_ptr(u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])),
+                        &m,
+                        AsPtr::as_mut_ptr(vt.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])),
+                        &n,
+                        AsPtr::as_mut_ptr(&mut work),
+                        &(lwork as i32),
+                        $(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                let s = unsafe { s.assume_init() };
+                let u = u.map(|v| unsafe { v.assume_init() });
+                let vt = vt.map(|v| unsafe { v.assume_init() });
+
+                match l {
+                    MatrixLayout::F { .. } => Ok(SVDOutput { s, u, vt }),
+                    MatrixLayout::C { .. } => Ok(SVDOutput { s, u: vt, vt: u }),
+                }
+            }
+        }
+    };
+} // impl_svd!
+
+impl_svd!(@real, f64, lapack_sys::dgesvd_);
+impl_svd!(@real, f32, lapack_sys::sgesvd_);
+impl_svd!(@complex, c64, lapack_sys::zgesvd_);
+impl_svd!(@complex, c32, lapack_sys::cgesvd_);
+
+
+ \ No newline at end of file diff --git a/src/lax/svddc.rs.html b/src/lax/svddc.rs.html new file mode 100644 index 00000000..85d7d376 --- /dev/null +++ b/src/lax/svddc.rs.html @@ -0,0 +1,296 @@ +svddc.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+
use crate::{error::*, layout::MatrixLayout, *};
+use cauchy::*;
+use num_traits::{ToPrimitive, Zero};
+
+/// Specifies how many of the columns of *U* and rows of *V*ᵀ are computed and returned.
+///
+/// For an input array of shape *m*×*n*, the following are computed:
+#[derive(Clone, Copy, Eq, PartialEq)]
+#[repr(u8)]
+pub enum UVTFlag {
+    /// All *m* columns of *U* and all *n* rows of *V*ᵀ.
+    Full = b'A',
+    /// The first min(*m*,*n*) columns of *U* and the first min(*m*,*n*) rows of *V*ᵀ.
+    Some = b'S',
+    /// No columns of *U* or rows of *V*ᵀ.
+    None = b'N',
+}
+
+impl UVTFlag {
+    fn as_ptr(&self) -> *const i8 {
+        self as *const UVTFlag as *const i8
+    }
+}
+
+pub trait SVDDC_: Scalar {
+    fn svddc(l: MatrixLayout, jobz: UVTFlag, a: &mut [Self]) -> Result<SVDOutput<Self>>;
+}
+
+macro_rules! impl_svddc {
+    (@real, $scalar:ty, $gesdd:path) => {
+        impl_svddc!(@body, $scalar, $gesdd, );
+    };
+    (@complex, $scalar:ty, $gesdd:path) => {
+        impl_svddc!(@body, $scalar, $gesdd, rwork);
+    };
+    (@body, $scalar:ty, $gesdd:path, $($rwork_ident:ident),*) => {
+        impl SVDDC_ for $scalar {
+            fn svddc(l: MatrixLayout, jobz: UVTFlag, a: &mut [Self],) -> Result<SVDOutput<Self>> {
+                let m = l.lda();
+                let n = l.len();
+                let k = m.min(n);
+                let mut s = unsafe { vec_uninit( k as usize) };
+
+                let (u_col, vt_row) = match jobz {
+                    UVTFlag::Full | UVTFlag::None => (m, n),
+                    UVTFlag::Some => (k, k),
+                };
+                let (mut u, mut vt) = match jobz {
+                    UVTFlag::Full => (
+                        Some(unsafe { vec_uninit( (m * m) as usize) }),
+                        Some(unsafe { vec_uninit( (n * n) as usize) }),
+                    ),
+                    UVTFlag::Some => (
+                        Some(unsafe { vec_uninit( (m * u_col) as usize) }),
+                        Some(unsafe { vec_uninit( (n * vt_row) as usize) }),
+                    ),
+                    UVTFlag::None => (None, None),
+                };
+
+                $( // for complex only
+                let mx = n.max(m) as usize;
+                let mn = n.min(m) as usize;
+                let lrwork = match jobz {
+                    UVTFlag::None => 7 * mn,
+                    _ => std::cmp::max(5*mn*mn + 5*mn, 2*mx*mn + 2*mn*mn + mn),
+                };
+                let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit( lrwork) };
+                )*
+
+                // eval work size
+                let mut info = 0;
+                let mut iwork: Vec<MaybeUninit<i32>> = unsafe { vec_uninit( 8 * k as usize) };
+                let mut work_size = [Self::zero()];
+                unsafe {
+                    $gesdd(
+                        jobz.as_ptr(),
+                        &m,
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &m,
+                        AsPtr::as_mut_ptr(&mut s),
+                        AsPtr::as_mut_ptr(u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])),
+                        &m,
+                        AsPtr::as_mut_ptr(vt.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])),
+                        &vt_row,
+                        AsPtr::as_mut_ptr(&mut work_size),
+                        &(-1),
+                        $(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
+                        AsPtr::as_mut_ptr(&mut iwork),
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                // do svd
+                let lwork = work_size[0].to_usize().unwrap();
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit( lwork) };
+                unsafe {
+                    $gesdd(
+                        jobz.as_ptr(),
+                        &m,
+                        &n,
+                        AsPtr::as_mut_ptr(a),
+                        &m,
+                        AsPtr::as_mut_ptr(&mut s),
+                        AsPtr::as_mut_ptr(u.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])),
+                        &m,
+                        AsPtr::as_mut_ptr(vt.as_mut().map(|x| x.as_mut_slice()).unwrap_or(&mut [])),
+                        &vt_row,
+                        AsPtr::as_mut_ptr(&mut work),
+                        &(lwork as i32),
+                        $(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
+                        AsPtr::as_mut_ptr(&mut iwork),
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                let s = unsafe { s.assume_init() };
+                let u = u.map(|v| unsafe { v.assume_init() });
+                let vt = vt.map(|v| unsafe { v.assume_init() });
+
+                match l {
+                    MatrixLayout::F { .. } => Ok(SVDOutput { s, u, vt }),
+                    MatrixLayout::C { .. } => Ok(SVDOutput { s, u: vt, vt: u }),
+                }
+            }
+        }
+    };
+}
+
+impl_svddc!(@real, f32, lapack_sys::sgesdd_);
+impl_svddc!(@real, f64, lapack_sys::dgesdd_);
+impl_svddc!(@complex, c32, lapack_sys::cgesdd_);
+impl_svddc!(@complex, c64, lapack_sys::zgesdd_);
+
+
+ \ No newline at end of file diff --git a/src/lax/triangular.rs.html b/src/lax/triangular.rs.html new file mode 100644 index 00000000..9ede8a07 --- /dev/null +++ b/src/lax/triangular.rs.html @@ -0,0 +1,222 @@ +triangular.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+
//! Implement linear solver and inverse matrix
+
+use crate::{error::*, layout::*, *};
+use cauchy::*;
+
+#[derive(Debug, Clone, Copy)]
+#[repr(u8)]
+pub enum Diag {
+    Unit = b'U',
+    NonUnit = b'N',
+}
+
+impl Diag {
+    fn as_ptr(&self) -> *const i8 {
+        self as *const Diag as *const i8
+    }
+}
+
+/// Wraps `*trtri` and `*trtrs`
+pub trait Triangular_: Scalar {
+    fn solve_triangular(
+        al: MatrixLayout,
+        bl: MatrixLayout,
+        uplo: UPLO,
+        d: Diag,
+        a: &[Self],
+        b: &mut [Self],
+    ) -> Result<()>;
+}
+
+macro_rules! impl_triangular {
+    ($scalar:ty, $trtri:path, $trtrs:path) => {
+        impl Triangular_ for $scalar {
+            fn solve_triangular(
+                a_layout: MatrixLayout,
+                b_layout: MatrixLayout,
+                uplo: UPLO,
+                diag: Diag,
+                a: &[Self],
+                b: &mut [Self],
+            ) -> Result<()> {
+                // Transpose if a is C-continuous
+                let mut a_t = None;
+                let a_layout = match a_layout {
+                    MatrixLayout::C { .. } => {
+                        let (layout, t) = transpose(a_layout, a);
+                        a_t = Some(t);
+                        layout
+                    }
+                    MatrixLayout::F { .. } => a_layout,
+                };
+
+                // Transpose if b is C-continuous
+                let mut b_t = None;
+                let b_layout = match b_layout {
+                    MatrixLayout::C { .. } => {
+                        let (layout, t) = transpose(b_layout, b);
+                        b_t = Some(t);
+                        layout
+                    }
+                    MatrixLayout::F { .. } => b_layout,
+                };
+
+                let (m, n) = a_layout.size();
+                let (n_, nrhs) = b_layout.size();
+                assert_eq!(n, n_);
+
+                let mut info = 0;
+                unsafe {
+                    $trtrs(
+                        uplo.as_ptr(),
+                        Transpose::No.as_ptr(),
+                        diag.as_ptr(),
+                        &m,
+                        &nrhs,
+                        AsPtr::as_ptr(a_t.as_ref().map(|v| v.as_slice()).unwrap_or(a)),
+                        &a_layout.lda(),
+                        AsPtr::as_mut_ptr(b_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(b)),
+                        &b_layout.lda(),
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+
+                // Re-transpose b
+                if let Some(b_t) = b_t {
+                    transpose_over(b_layout, &b_t, b);
+                }
+                Ok(())
+            }
+        }
+    };
+} // impl_triangular!
+
+impl_triangular!(f64, lapack_sys::dtrtri_, lapack_sys::dtrtrs_);
+impl_triangular!(f32, lapack_sys::strtri_, lapack_sys::strtrs_);
+impl_triangular!(c64, lapack_sys::ztrtri_, lapack_sys::ztrtrs_);
+impl_triangular!(c32, lapack_sys::ctrtri_, lapack_sys::ctrtrs_);
+
+
+ \ No newline at end of file diff --git a/src/lax/tridiagonal.rs.html b/src/lax/tridiagonal.rs.html new file mode 100644 index 00000000..d68902ac --- /dev/null +++ b/src/lax/tridiagonal.rs.html @@ -0,0 +1,544 @@ +tridiagonal.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+
//! Implement linear solver using LU decomposition
+//! for tridiagonal matrix
+
+use crate::{error::*, layout::*, *};
+use cauchy::*;
+use num_traits::Zero;
+use std::ops::{Index, IndexMut};
+
+/// Represents a tridiagonal matrix as 3 one-dimensional vectors.
+///
+/// ```text
+/// [d0, u1,  0,   ...,       0,
+///  l1, d1, u2,            ...,
+///   0, l2, d2,
+///  ...           ...,  u{n-1},
+///   0,  ...,  l{n-1},  d{n-1},]
+/// ```
+#[derive(Clone, PartialEq, Eq)]
+pub struct Tridiagonal<A: Scalar> {
+    /// layout of raw matrix
+    pub l: MatrixLayout,
+    /// (n-1) sub-diagonal elements of matrix.
+    pub dl: Vec<A>,
+    /// (n) diagonal elements of matrix.
+    pub d: Vec<A>,
+    /// (n-1) super-diagonal elements of matrix.
+    pub du: Vec<A>,
+}
+
+impl<A: Scalar> Tridiagonal<A> {
+    fn opnorm_one(&self) -> A::Real {
+        let mut col_sum: Vec<A::Real> = self.d.iter().map(|val| val.abs()).collect();
+        for i in 0..col_sum.len() {
+            if i < self.dl.len() {
+                col_sum[i] += self.dl[i].abs();
+            }
+            if i > 0 {
+                col_sum[i] += self.du[i - 1].abs();
+            }
+        }
+        let mut max = A::Real::zero();
+        for &val in &col_sum {
+            if max < val {
+                max = val;
+            }
+        }
+        max
+    }
+}
+
+/// Represents the LU factorization of a tridiagonal matrix `A` as `A = P*L*U`.
+#[derive(Clone, PartialEq)]
+pub struct LUFactorizedTridiagonal<A: Scalar> {
+    /// A tridiagonal matrix which consists of
+    /// - l : layout of raw matrix
+    /// - dl: (n-1) multipliers that define the matrix L.
+    /// - d : (n) diagonal elements of the upper triangular matrix U.
+    /// - du: (n-1) elements of the first super-diagonal of U.
+    pub a: Tridiagonal<A>,
+    /// (n-2) elements of the second super-diagonal of U.
+    pub du2: Vec<A>,
+    /// The pivot indices that define the permutation matrix `P`.
+    pub ipiv: Pivot,
+
+    a_opnorm_one: A::Real,
+}
+
+impl<A: Scalar> Index<(i32, i32)> for Tridiagonal<A> {
+    type Output = A;
+    #[inline]
+    fn index(&self, (row, col): (i32, i32)) -> &A {
+        let (n, _) = self.l.size();
+        assert!(
+            std::cmp::max(row, col) < n,
+            "ndarray: index {:?} is out of bounds for array of shape {}",
+            [row, col],
+            n
+        );
+        match row - col {
+            0 => &self.d[row as usize],
+            1 => &self.dl[col as usize],
+            -1 => &self.du[row as usize],
+            _ => panic!(
+                "ndarray-linalg::tridiagonal: index {:?} is not tridiagonal element",
+                [row, col]
+            ),
+        }
+    }
+}
+
+impl<A: Scalar> Index<[i32; 2]> for Tridiagonal<A> {
+    type Output = A;
+    #[inline]
+    fn index(&self, [row, col]: [i32; 2]) -> &A {
+        &self[(row, col)]
+    }
+}
+
+impl<A: Scalar> IndexMut<(i32, i32)> for Tridiagonal<A> {
+    #[inline]
+    fn index_mut(&mut self, (row, col): (i32, i32)) -> &mut A {
+        let (n, _) = self.l.size();
+        assert!(
+            std::cmp::max(row, col) < n,
+            "ndarray: index {:?} is out of bounds for array of shape {}",
+            [row, col],
+            n
+        );
+        match row - col {
+            0 => &mut self.d[row as usize],
+            1 => &mut self.dl[col as usize],
+            -1 => &mut self.du[row as usize],
+            _ => panic!(
+                "ndarray-linalg::tridiagonal: index {:?} is not tridiagonal element",
+                [row, col]
+            ),
+        }
+    }
+}
+
+impl<A: Scalar> IndexMut<[i32; 2]> for Tridiagonal<A> {
+    #[inline]
+    fn index_mut(&mut self, [row, col]: [i32; 2]) -> &mut A {
+        &mut self[(row, col)]
+    }
+}
+
+/// Wraps `*gttrf`, `*gtcon` and `*gttrs`
+pub trait Tridiagonal_: Scalar + Sized {
+    /// Computes the LU factorization of a tridiagonal `m x n` matrix `a` using
+    /// partial pivoting with row interchanges.
+    fn lu_tridiagonal(a: Tridiagonal<Self>) -> Result<LUFactorizedTridiagonal<Self>>;
+
+    fn rcond_tridiagonal(lu: &LUFactorizedTridiagonal<Self>) -> Result<Self::Real>;
+
+    fn solve_tridiagonal(
+        lu: &LUFactorizedTridiagonal<Self>,
+        bl: MatrixLayout,
+        t: Transpose,
+        b: &mut [Self],
+    ) -> Result<()>;
+}
+
+macro_rules! impl_tridiagonal {
+    (@real, $scalar:ty, $gttrf:path, $gtcon:path, $gttrs:path) => {
+        impl_tridiagonal!(@body, $scalar, $gttrf, $gtcon, $gttrs, iwork);
+    };
+    (@complex, $scalar:ty, $gttrf:path, $gtcon:path, $gttrs:path) => {
+        impl_tridiagonal!(@body, $scalar, $gttrf, $gtcon, $gttrs, );
+    };
+    (@body, $scalar:ty, $gttrf:path, $gtcon:path, $gttrs:path, $($iwork:ident)*) => {
+        impl Tridiagonal_ for $scalar {
+            fn lu_tridiagonal(mut a: Tridiagonal<Self>) -> Result<LUFactorizedTridiagonal<Self>> {
+                let (n, _) = a.l.size();
+                let mut du2 = unsafe { vec_uninit( (n - 2) as usize) };
+                let mut ipiv = unsafe { vec_uninit( n as usize) };
+                // We have to calc one-norm before LU factorization
+                let a_opnorm_one = a.opnorm_one();
+                let mut info = 0;
+                unsafe {
+                    $gttrf(
+                        &n,
+                        AsPtr::as_mut_ptr(&mut a.dl),
+                        AsPtr::as_mut_ptr(&mut a.d),
+                        AsPtr::as_mut_ptr(&mut a.du),
+                        AsPtr::as_mut_ptr(&mut du2),
+                        AsPtr::as_mut_ptr(&mut ipiv),
+                        &mut info,
+                    )
+                };
+                info.as_lapack_result()?;
+                let du2 = unsafe { du2.assume_init() };
+                let ipiv = unsafe { ipiv.assume_init() };
+                Ok(LUFactorizedTridiagonal {
+                    a,
+                    du2,
+                    ipiv,
+                    a_opnorm_one,
+                })
+            }
+
+            fn rcond_tridiagonal(lu: &LUFactorizedTridiagonal<Self>) -> Result<Self::Real> {
+                let (n, _) = lu.a.l.size();
+                let ipiv = &lu.ipiv;
+                let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit( 2 * n as usize) };
+                $(
+                let mut $iwork: Vec<MaybeUninit<i32>> = unsafe { vec_uninit( n as usize) };
+                )*
+                let mut rcond = Self::Real::zero();
+                let mut info = 0;
+                unsafe {
+                    $gtcon(
+                        NormType::One.as_ptr(),
+                        &n,
+                        AsPtr::as_ptr(&lu.a.dl),
+                        AsPtr::as_ptr(&lu.a.d),
+                        AsPtr::as_ptr(&lu.a.du),
+                        AsPtr::as_ptr(&lu.du2),
+                        ipiv.as_ptr(),
+                        &lu.a_opnorm_one,
+                        &mut rcond,
+                        AsPtr::as_mut_ptr(&mut work),
+                        $(AsPtr::as_mut_ptr(&mut $iwork),)*
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+                Ok(rcond)
+            }
+
+            fn solve_tridiagonal(
+                lu: &LUFactorizedTridiagonal<Self>,
+                b_layout: MatrixLayout,
+                t: Transpose,
+                b: &mut [Self],
+            ) -> Result<()> {
+                let (n, _) = lu.a.l.size();
+                let ipiv = &lu.ipiv;
+                // Transpose if b is C-continuous
+                let mut b_t = None;
+                let b_layout = match b_layout {
+                    MatrixLayout::C { .. } => {
+                        let (layout, t) = transpose(b_layout, b);
+                        b_t = Some(t);
+                        layout
+                    }
+                    MatrixLayout::F { .. } => b_layout,
+                };
+                let (ldb, nrhs) = b_layout.size();
+                let mut info = 0;
+                unsafe {
+                    $gttrs(
+                        t.as_ptr(),
+                        &n,
+                        &nrhs,
+                        AsPtr::as_ptr(&lu.a.dl),
+                        AsPtr::as_ptr(&lu.a.d),
+                        AsPtr::as_ptr(&lu.a.du),
+                        AsPtr::as_ptr(&lu.du2),
+                        ipiv.as_ptr(),
+                        AsPtr::as_mut_ptr(b_t.as_mut().map(|v| v.as_mut_slice()).unwrap_or(b)),
+                        &ldb,
+                        &mut info,
+                    );
+                }
+                info.as_lapack_result()?;
+                if let Some(b_t) = b_t {
+                    transpose_over(b_layout, &b_t, b);
+                }
+                Ok(())
+            }
+        }
+    };
+} // impl_tridiagonal!
+
+impl_tridiagonal!(@real, f64, lapack_sys::dgttrf_, lapack_sys::dgtcon_, lapack_sys::dgttrs_);
+impl_tridiagonal!(@real, f32, lapack_sys::sgttrf_, lapack_sys::sgtcon_, lapack_sys::sgttrs_);
+impl_tridiagonal!(@complex, c64, lapack_sys::zgttrf_, lapack_sys::zgtcon_, lapack_sys::zgttrs_);
+impl_tridiagonal!(@complex, c32, lapack_sys::cgttrf_, lapack_sys::cgtcon_, lapack_sys::cgttrs_);
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/assert.rs.html b/src/ndarray_linalg/assert.rs.html new file mode 100644 index 00000000..868df816 --- /dev/null +++ b/src/ndarray_linalg/assert.rs.html @@ -0,0 +1,240 @@ +assert.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+
//! Assertions for array
+
+use ndarray::*;
+use std::fmt::Debug;
+
+use super::norm::*;
+use super::types::*;
+
+/// check two values are close in terms of the relative tolerance
+pub fn rclose<A: Scalar>(test: A, truth: A, rtol: A::Real) {
+    let dev = (test - truth).abs() / truth.abs();
+    if dev > rtol {
+        eprintln!("==== Assetion Failed ====");
+        eprintln!("Expected = {}", truth);
+        eprintln!("Actual   = {}", test);
+        panic!("Too large deviation in relative tolerance: {}", dev);
+    }
+}
+
+/// check two values are close in terms of the absolute tolerance
+pub fn aclose<A: Scalar>(test: A, truth: A, atol: A::Real) {
+    let dev = (test - truth).abs();
+    if dev > atol {
+        eprintln!("==== Assetion Failed ====");
+        eprintln!("Expected = {}", truth);
+        eprintln!("Actual   = {}", test);
+        panic!("Too large deviation in absolute tolerance: {}", dev);
+    }
+}
+
+/// check two arrays are close in maximum norm
+pub fn close_max<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, atol: A::Real)
+where
+    A: Scalar + Lapack,
+    S1: Data<Elem = A>,
+    S2: Data<Elem = A>,
+    D: Dimension,
+    D::Pattern: PartialEq + Debug,
+{
+    assert_eq!(test.dim(), truth.dim());
+    let tol = (test - truth).norm_max();
+    if tol > atol {
+        eprintln!("==== Assetion Failed ====");
+        eprintln!("Expected:\n{}", truth);
+        eprintln!("Actual:\n{}", test);
+        panic!("Too large deviation in maximum norm: {} > {}", tol, atol);
+    }
+}
+
+/// check two arrays are close in L1 norm
+pub fn close_l1<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, rtol: A::Real)
+where
+    A: Scalar + Lapack,
+    S1: Data<Elem = A>,
+    S2: Data<Elem = A>,
+    D: Dimension,
+    D::Pattern: PartialEq + Debug,
+{
+    assert_eq!(test.dim(), truth.dim());
+    let tol = (test - truth).norm_l1() / truth.norm_l1();
+    if tol > rtol {
+        eprintln!("==== Assetion Failed ====");
+        eprintln!("Expected:\n{}", truth);
+        eprintln!("Actual:\n{}", test);
+        panic!("Too large deviation in L1-norm: {} > {}", tol, rtol);
+    }
+}
+
+/// check two arrays are close in L2 norm
+pub fn close_l2<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, rtol: A::Real)
+where
+    A: Scalar + Lapack,
+    S1: Data<Elem = A>,
+    S2: Data<Elem = A>,
+    D: Dimension,
+    D::Pattern: PartialEq + Debug,
+{
+    assert_eq!(test.dim(), truth.dim());
+    let tol = (test - truth).norm_l2() / truth.norm_l2();
+    if tol > rtol {
+        eprintln!("==== Assetion Failed ====");
+        eprintln!("Expected:\n{}", truth);
+        eprintln!("Actual:\n{}", test);
+        panic!("Too large deviation in L2-norm: {} > {} ", tol, rtol);
+    }
+}
+
+macro_rules! generate_assert {
+    ($assert:ident, $close:path) => {
+        #[macro_export]
+        macro_rules! $assert {
+            ($test: expr,$truth: expr,$tol: expr) => {
+                $crate::$close($test, $truth, $tol);
+            };
+            ($test: expr,$truth: expr,$tol: expr; $comment: expr) => {
+                eprintln!($comment);
+                $crate::$close($test, $truth, $tol);
+            };
+        }
+    };
+} // generate_assert!
+
+generate_assert!(assert_rclose, rclose);
+generate_assert!(assert_aclose, aclose);
+generate_assert!(assert_close_max, close_max);
+generate_assert!(assert_close_l1, close_l1);
+generate_assert!(assert_close_l2, close_l2);
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/cholesky.rs.html b/src/ndarray_linalg/cholesky.rs.html new file mode 100644 index 00000000..f0aaee63 --- /dev/null +++ b/src/ndarray_linalg/cholesky.rs.html @@ -0,0 +1,962 @@ +cholesky.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+
//! Cholesky decomposition of Hermitian (or real symmetric) positive definite matrices
+//!
+//! See the [Wikipedia page about Cholesky
+//! decomposition](https://en.wikipedia.org/wiki/Cholesky_decomposition) for
+//! more information.
+//!
+//! # Example
+//!
+//! Using the Cholesky decomposition of `A` for various operations, where `A`
+//! is a Hermitian (or real symmetric) positive definite matrix:
+//!
+//! ```
+//! #[macro_use]
+//! extern crate ndarray;
+//! extern crate ndarray_linalg;
+//!
+//! use ndarray::prelude::*;
+//! use ndarray_linalg::cholesky::*;
+//! # fn main() {
+//!
+//! let a: Array2<f64> = array![
+//!     [  4.,  12., -16.],
+//!     [ 12.,  37., -43.],
+//!     [-16., -43.,  98.]
+//! ];
+//!
+//! // Obtain `L`
+//! let lower = a.cholesky(UPLO::Lower).unwrap();
+//! assert!(lower.abs_diff_eq(&array![
+//!     [ 2., 0., 0.],
+//!     [ 6., 1., 0.],
+//!     [-8., 5., 3.]
+//! ], 1e-9));
+//!
+//! // Find the determinant of `A`
+//! let det = a.detc().unwrap();
+//! assert!((det - 36.).abs() < 1e-9);
+//!
+//! // Solve `A * x = b`
+//! let b = array![4., 13., -11.];
+//! let x = a.solvec(&b).unwrap();
+//! assert!(x.abs_diff_eq(&array![-2., 1., 0.], 1e-9));
+//! # }
+//! ```
+
+use ndarray::*;
+use num_traits::Float;
+
+use crate::convert::*;
+use crate::error::*;
+use crate::layout::*;
+use crate::triangular::IntoTriangular;
+use crate::types::*;
+
+pub use lax::UPLO;
+
+/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix
+pub struct CholeskyFactorized<S: Data> {
+    /// `L` from the decomposition `A = L * L^H` or `U` from the decomposition
+    /// `A = U^H * U`.
+    pub factor: ArrayBase<S, Ix2>,
+    /// If this is `UPLO::Lower`, then `self.factor` is `L`. If this is
+    /// `UPLO::Upper`, then `self.factor` is `U`.
+    pub uplo: UPLO,
+}
+
+impl<A, S> CholeskyFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    /// Returns `L` from the Cholesky decomposition `A = L * L^H`.
+    ///
+    /// If `self.uplo == UPLO::Lower`, then no computations need to be
+    /// performed; otherwise, the conjugate transpose of `self.factor` is
+    /// calculated.
+    pub fn into_lower(self) -> ArrayBase<S, Ix2> {
+        match self.uplo {
+            UPLO::Lower => self.factor,
+            UPLO::Upper => self.factor.reversed_axes().mapv_into(|elem| elem.conj()),
+        }
+    }
+
+    /// Returns `U` from the Cholesky decomposition `A = U^H * U`.
+    ///
+    /// If `self.uplo == UPLO::Upper`, then no computations need to be
+    /// performed; otherwise, the conjugate transpose of `self.factor` is
+    /// calculated.
+    pub fn into_upper(self) -> ArrayBase<S, Ix2> {
+        match self.uplo {
+            UPLO::Lower => self.factor.reversed_axes().mapv_into(|elem| elem.conj()),
+            UPLO::Upper => self.factor,
+        }
+    }
+}
+
+impl<A, S> DeterminantC for CholeskyFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = <A as Scalar>::Real;
+
+    fn detc(&self) -> Self::Output {
+        Float::exp(self.ln_detc())
+    }
+
+    fn ln_detc(&self) -> Self::Output {
+        self.factor
+            .diag()
+            .iter()
+            .map(|elem| Float::ln(elem.square()))
+            .sum::<Self::Output>()
+    }
+}
+
+impl<A, S> DeterminantCInto for CholeskyFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = <A as Scalar>::Real;
+
+    fn detc_into(self) -> Self::Output {
+        self.detc()
+    }
+
+    fn ln_detc_into(self) -> Self::Output {
+        self.ln_detc()
+    }
+}
+
+impl<A, S> InverseC for CholeskyFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = Array2<A>;
+
+    fn invc(&self) -> Result<Self::Output> {
+        let f = CholeskyFactorized {
+            factor: replicate(&self.factor),
+            uplo: self.uplo,
+        };
+        f.invc_into()
+    }
+}
+
+impl<A, S> InverseCInto for CholeskyFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type Output = ArrayBase<S, Ix2>;
+
+    fn invc_into(self) -> Result<Self::Output> {
+        let mut a = self.factor;
+        A::inv_cholesky(a.square_layout()?, self.uplo, a.as_allocated_mut()?)?;
+        triangular_fill_hermitian(&mut a, self.uplo);
+        Ok(a)
+    }
+}
+
+impl<A, S> SolveC<A> for CholeskyFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn solvec_inplace<'a, Sb>(
+        &self,
+        b: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        A::solve_cholesky(
+            self.factor.square_layout()?,
+            self.uplo,
+            self.factor.as_allocated()?,
+            b.as_slice_mut().unwrap(),
+        )?;
+        Ok(b)
+    }
+}
+
+/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference
+pub trait Cholesky {
+    type Output;
+
+    /// Computes the Cholesky decomposition of the Hermitian (or real
+    /// symmetric) positive definite matrix.
+    ///
+    /// If the argument is `UPLO::Upper`, then computes the decomposition `A =
+    /// U^H * U` using the upper triangular portion of `A` and returns `U`.
+    /// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition
+    /// `A = L * L^H` using the lower triangular portion of `A` and returns
+    /// `L`.
+    fn cholesky(&self, uplo: UPLO) -> Result<Self::Output>;
+}
+
+/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix
+pub trait CholeskyInto {
+    type Output;
+    /// Computes the Cholesky decomposition of the Hermitian (or real
+    /// symmetric) positive definite matrix.
+    ///
+    /// If the argument is `UPLO::Upper`, then computes the decomposition `A =
+    /// U^H * U` using the upper triangular portion of `A` and returns `U`.
+    /// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition
+    /// `A = L * L^H` using the lower triangular portion of `A` and returns
+    /// `L`.
+    fn cholesky_into(self, uplo: UPLO) -> Result<Self::Output>;
+}
+
+/// Cholesky decomposition of Hermitian (or real symmetric) positive definite mutable reference of matrix
+pub trait CholeskyInplace {
+    /// Computes the Cholesky decomposition of the Hermitian (or real
+    /// symmetric) positive definite matrix, writing the result (`L` or `U`
+    /// according to the argument) to `self` and returning it.
+    ///
+    /// If the argument is `UPLO::Upper`, then computes the decomposition `A =
+    /// U^H * U` using the upper triangular portion of `A` and writes `U`.
+    /// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition
+    /// `A = L * L^H` using the lower triangular portion of `A` and writes `L`.
+    fn cholesky_inplace(&mut self, uplo: UPLO) -> Result<&mut Self>;
+}
+
+impl<A, S> Cholesky for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = Array2<A>;
+
+    fn cholesky(&self, uplo: UPLO) -> Result<Array2<A>> {
+        let a = replicate(self);
+        a.cholesky_into(uplo)
+    }
+}
+
+impl<A, S> CholeskyInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type Output = Self;
+
+    fn cholesky_into(mut self, uplo: UPLO) -> Result<Self> {
+        self.cholesky_inplace(uplo)?;
+        Ok(self)
+    }
+}
+
+impl<A, S> CholeskyInplace for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    fn cholesky_inplace(&mut self, uplo: UPLO) -> Result<&mut Self> {
+        A::cholesky(self.square_layout()?, uplo, self.as_allocated_mut()?)?;
+        Ok(self.into_triangular(uplo))
+    }
+}
+
+/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference
+pub trait FactorizeC<S: Data> {
+    /// Computes the Cholesky decomposition of the Hermitian (or real
+    /// symmetric) positive definite matrix.
+    ///
+    /// If the argument is `UPLO::Upper`, then computes the decomposition `A =
+    /// U^H * U` using the upper triangular portion of `A` and returns the
+    /// factorization containing `U`. Otherwise, if the argument is
+    /// `UPLO::Lower`, computes the decomposition `A = L * L^H` using the lower
+    /// triangular portion of `A` and returns the factorization containing `L`.
+    fn factorizec(&self, uplo: UPLO) -> Result<CholeskyFactorized<S>>;
+}
+
+/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix
+pub trait FactorizeCInto<S: Data> {
+    /// Computes the Cholesky decomposition of the Hermitian (or real
+    /// symmetric) positive definite matrix.
+    ///
+    /// If the argument is `UPLO::Upper`, then computes the decomposition `A =
+    /// U^H * U` using the upper triangular portion of `A` and returns the
+    /// factorization containing `U`. Otherwise, if the argument is
+    /// `UPLO::Lower`, computes the decomposition `A = L * L^H` using the lower
+    /// triangular portion of `A` and returns the factorization containing `L`.
+    fn factorizec_into(self, uplo: UPLO) -> Result<CholeskyFactorized<S>>;
+}
+
+impl<A, S> FactorizeCInto<S> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    fn factorizec_into(self, uplo: UPLO) -> Result<CholeskyFactorized<S>> {
+        Ok(CholeskyFactorized {
+            factor: self.cholesky_into(uplo)?,
+            uplo,
+        })
+    }
+}
+
+impl<A, Si> FactorizeC<OwnedRepr<A>> for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+{
+    fn factorizec(&self, uplo: UPLO) -> Result<CholeskyFactorized<OwnedRepr<A>>> {
+        Ok(CholeskyFactorized {
+            factor: self.cholesky(uplo)?,
+            uplo,
+        })
+    }
+}
+
+/// Solve systems of linear equations with Hermitian (or real symmetric)
+/// positive definite coefficient matrices
+pub trait SolveC<A: Scalar> {
+    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
+    /// symmetric) positive definite matrix `A`, where `A` is `self`, `b` is
+    /// the argument, and `x` is the successful result.
+    fn solvec<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
+        let mut b = replicate(b);
+        self.solvec_inplace(&mut b)?;
+        Ok(b)
+    }
+    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
+    /// symmetric) positive definite matrix `A`, where `A` is `self`, `b` is
+    /// the argument, and `x` is the successful result.
+    fn solvec_into<S: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<S, Ix1>,
+    ) -> Result<ArrayBase<S, Ix1>> {
+        self.solvec_inplace(&mut b)?;
+        Ok(b)
+    }
+    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
+    /// symmetric) positive definite matrix `A`, where `A` is `self`, `b` is
+    /// the argument, and `x` is the successful result. The value of `x` is
+    /// also assigned to the argument.
+    fn solvec_inplace<'a, S: DataMut<Elem = A>>(
+        &self,
+        b: &'a mut ArrayBase<S, Ix1>,
+    ) -> Result<&'a mut ArrayBase<S, Ix1>>;
+}
+
+impl<A, S> SolveC<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn solvec_inplace<'a, Sb>(
+        &self,
+        b: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        self.factorizec(UPLO::Upper)?.solvec_inplace(b)
+    }
+}
+
+/// Inverse of Hermitian (or real symmetric) positive definite matrix ref
+pub trait InverseC {
+    type Output;
+    /// Computes the inverse of the Hermitian (or real symmetric) positive
+    /// definite matrix.
+    fn invc(&self) -> Result<Self::Output>;
+}
+
+/// Inverse of Hermitian (or real symmetric) positive definite matrix
+pub trait InverseCInto {
+    type Output;
+    /// Computes the inverse of the Hermitian (or real symmetric) positive
+    /// definite matrix.
+    fn invc_into(self) -> Result<Self::Output>;
+}
+
+impl<A, S> InverseC for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = Array2<A>;
+
+    fn invc(&self) -> Result<Self::Output> {
+        self.factorizec(UPLO::Upper)?.invc_into()
+    }
+}
+
+impl<A, S> InverseCInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type Output = Self;
+
+    fn invc_into(self) -> Result<Self::Output> {
+        self.factorizec_into(UPLO::Upper)?.invc_into()
+    }
+}
+
+/// Determinant of Hermitian (or real symmetric) positive definite matrix ref
+pub trait DeterminantC {
+    type Output;
+
+    /// Computes the determinant of the Hermitian (or real symmetric) positive
+    /// definite matrix.
+    fn detc(&self) -> Self::Output;
+
+    /// Computes the natural log of the determinant of the Hermitian (or real
+    /// symmetric) positive definite matrix.
+    ///
+    /// This method is more robust than `.detc()` to very small or very large
+    /// determinants since it returns the natural logarithm of the determinant
+    /// rather than the determinant itself.
+    fn ln_detc(&self) -> Self::Output;
+}
+
+/// Determinant of Hermitian (or real symmetric) positive definite matrix
+pub trait DeterminantCInto {
+    type Output;
+
+    /// Computes the determinant of the Hermitian (or real symmetric) positive
+    /// definite matrix.
+    fn detc_into(self) -> Self::Output;
+
+    /// Computes the natural log of the determinant of the Hermitian (or real
+    /// symmetric) positive definite matrix.
+    ///
+    /// This method is more robust than `.detc_into()` to very small or very
+    /// large determinants since it returns the natural logarithm of the
+    /// determinant rather than the determinant itself.
+    fn ln_detc_into(self) -> Self::Output;
+}
+
+impl<A, S> DeterminantC for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = Result<<A as Scalar>::Real>;
+
+    fn detc(&self) -> Self::Output {
+        Ok(Float::exp(self.ln_detc()?))
+    }
+
+    fn ln_detc(&self) -> Self::Output {
+        Ok(self.factorizec(UPLO::Upper)?.ln_detc())
+    }
+}
+
+impl<A, S> DeterminantCInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type Output = Result<<A as Scalar>::Real>;
+
+    fn detc_into(self) -> Self::Output {
+        Ok(Float::exp(self.ln_detc_into()?))
+    }
+
+    fn ln_detc_into(self) -> Self::Output {
+        Ok(self.factorizec_into(UPLO::Upper)?.ln_detc_into())
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/convert.rs.html b/src/ndarray_linalg/convert.rs.html new file mode 100644 index 00000000..93583f51 --- /dev/null +++ b/src/ndarray_linalg/convert.rs.html @@ -0,0 +1,314 @@ +convert.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+
//! utilities for convert array
+
+use lax::UPLO;
+use ndarray::*;
+
+use super::error::*;
+use super::layout::*;
+use super::types::*;
+
+pub fn into_col<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
+where
+    S: Data,
+{
+    let n = a.len();
+    a.into_shape((n, 1)).unwrap()
+}
+
+pub fn into_row<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
+where
+    S: Data,
+{
+    let n = a.len();
+    a.into_shape((1, n)).unwrap()
+}
+
+pub fn flatten<S>(a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix1>
+where
+    S: Data,
+{
+    let n = a.len();
+    a.into_shape(n).unwrap()
+}
+
+pub fn into_matrix<A, S>(l: MatrixLayout, a: Vec<A>) -> Result<ArrayBase<S, Ix2>>
+where
+    S: DataOwned<Elem = A>,
+{
+    match l {
+        MatrixLayout::C { row, lda } => {
+            Ok(ArrayBase::from_shape_vec((row as usize, lda as usize), a)?)
+        }
+        MatrixLayout::F { col, lda } => Ok(ArrayBase::from_shape_vec(
+            (lda as usize, col as usize).f(),
+            a,
+        )?),
+    }
+}
+
+pub fn replicate<A, Sv, So, D>(a: &ArrayBase<Sv, D>) -> ArrayBase<So, D>
+where
+    A: Copy,
+    Sv: Data<Elem = A>,
+    So: DataOwned<Elem = A> + DataMut,
+    D: Dimension,
+{
+    unsafe {
+        let ret = ArrayBase::<So, D>::build_uninit(a.dim(), |view| {
+            a.assign_to(view);
+        });
+        ret.assume_init()
+    }
+}
+
+fn clone_with_layout<A, Si, So>(l: MatrixLayout, a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
+where
+    A: Copy,
+    Si: Data<Elem = A>,
+    So: DataOwned<Elem = A> + DataMut,
+{
+    let shape_builder = match l {
+        MatrixLayout::C { row, lda } => (row as usize, lda as usize).set_f(false),
+        MatrixLayout::F { col, lda } => (lda as usize, col as usize).set_f(true),
+    };
+    unsafe {
+        let ret = ArrayBase::<So, _>::build_uninit(shape_builder, |view| {
+            a.assign_to(view);
+        });
+        ret.assume_init()
+    }
+}
+
+pub fn transpose_data<A, S>(a: &mut ArrayBase<S, Ix2>) -> Result<&mut ArrayBase<S, Ix2>>
+where
+    A: Copy,
+    S: DataOwned<Elem = A> + DataMut,
+{
+    let l = a.layout()?.toggle_order();
+    let new = clone_with_layout(l, a);
+    *a = new;
+    Ok(a)
+}
+
+pub fn generalize<A, S, D>(a: Array<A, D>) -> ArrayBase<S, D>
+where
+    S: DataOwned<Elem = A>,
+    D: Dimension,
+{
+    // FIXME
+    // https://github.com/bluss/rust-ndarray/issues/325
+    let strides: Vec<isize> = a.strides().to_vec();
+    let new = if a.is_standard_layout() {
+        ArrayBase::from_shape_vec(a.dim(), a.into_raw_vec()).unwrap()
+    } else {
+        ArrayBase::from_shape_vec(a.dim().f(), a.into_raw_vec()).unwrap()
+    };
+    assert_eq!(
+        new.strides(),
+        strides.as_slice(),
+        "Custom stride is not supported"
+    );
+    new
+}
+
+/// Fills in the remainder of a Hermitian matrix that's represented by only one
+/// triangle.
+///
+/// LAPACK methods on Hermitian matrices usually read/write only one triangular
+/// portion of the matrix. This function fills in the other half based on the
+/// data in the triangular portion corresponding to `uplo`.
+///
+/// ***Panics*** if `a` is not square.
+pub(crate) fn triangular_fill_hermitian<A, S>(a: &mut ArrayBase<S, Ix2>, uplo: UPLO)
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    assert!(a.is_square());
+    match uplo {
+        UPLO::Upper => {
+            for row in 0..a.nrows() {
+                for col in 0..row {
+                    a[(row, col)] = a[(col, row)].conj();
+                }
+            }
+        }
+        UPLO::Lower => {
+            for col in 0..a.ncols() {
+                for row in 0..col {
+                    a[(row, col)] = a[(col, row)].conj();
+                }
+            }
+        }
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/diagonal.rs.html b/src/ndarray_linalg/diagonal.rs.html new file mode 100644 index 00000000..05571a76 --- /dev/null +++ b/src/ndarray_linalg/diagonal.rs.html @@ -0,0 +1,122 @@ +diagonal.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+
//! Vector as a Diagonal matrix
+
+use ndarray::*;
+
+use super::operator::*;
+use super::types::*;
+
+/// Vector as a Diagonal matrix
+pub struct Diagonal<S: Data> {
+    diag: ArrayBase<S, Ix1>,
+}
+
+pub trait IntoDiagonal<S: Data> {
+    fn into_diagonal(self) -> Diagonal<S>;
+}
+
+pub trait AsDiagonal<A> {
+    fn as_diagonal(&self) -> Diagonal<ViewRepr<&A>>;
+}
+
+impl<S: Data> IntoDiagonal<S> for ArrayBase<S, Ix1> {
+    fn into_diagonal(self) -> Diagonal<S> {
+        Diagonal { diag: self }
+    }
+}
+
+impl<A, S: Data<Elem = A>> AsDiagonal<A> for ArrayBase<S, Ix1> {
+    fn as_diagonal(&self) -> Diagonal<ViewRepr<&A>> {
+        Diagonal { diag: self.view() }
+    }
+}
+
+impl<A, Sa> LinearOperator for Diagonal<Sa>
+where
+    A: Scalar,
+    Sa: Data<Elem = A>,
+{
+    type Elem = A;
+
+    fn apply_mut<S>(&self, a: &mut ArrayBase<S, Ix1>)
+    where
+        S: DataMut<Elem = A>,
+    {
+        for (val, d) in a.iter_mut().zip(self.diag.iter()) {
+            *val *= *d;
+        }
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/eig.rs.html b/src/ndarray_linalg/eig.rs.html new file mode 100644 index 00000000..04afa496 --- /dev/null +++ b/src/ndarray_linalg/eig.rs.html @@ -0,0 +1,182 @@ +eig.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+
//! Eigenvalue decomposition for non-symmetric square matrices
+
+use crate::error::*;
+use crate::layout::*;
+use crate::types::*;
+use ndarray::*;
+
+/// Eigenvalue decomposition of general matrix reference
+pub trait Eig {
+    /// EigVec is the right eivenvector
+    type EigVal;
+    type EigVec;
+    /// Calculate eigenvalues with the right eigenvector
+    ///
+    /// $$ A u_i = \lambda_i u_i $$
+    ///
+    /// ```
+    /// use ndarray::*;
+    /// use ndarray_linalg::*;
+    ///
+    /// let a: Array2<f64> = array![
+    ///     [-1.01,  0.86, -4.60,  3.31, -4.81],
+    ///     [ 3.98,  0.53, -7.04,  5.29,  3.55],
+    ///     [ 3.30,  8.26, -3.89,  8.20, -1.51],
+    ///     [ 4.43,  4.96, -7.66, -7.33,  6.18],
+    ///     [ 7.31, -6.43, -6.16,  2.47,  5.58],
+    /// ];
+    /// let (eigs, vecs) = a.eig().unwrap();
+    ///
+    /// let a = a.map(|v| v.as_c());
+    /// for (&e, vec) in eigs.iter().zip(vecs.axis_iter(Axis(1))) {
+    ///     let ev = vec.map(|v| v * e);
+    ///     let av = a.dot(&vec);
+    ///     assert_close_l2!(&av, &ev, 1e-5);
+    /// }
+    /// ```
+    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>;
+}
+
+impl<A, S> Eig for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type EigVal = Array1<A::Complex>;
+    type EigVec = Array2<A::Complex>;
+
+    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)> {
+        let mut a = self.to_owned();
+        let layout = a.square_layout()?;
+        let (s, t) = A::eig(true, layout, a.as_allocated_mut()?)?;
+        let n = layout.len() as usize;
+        Ok((
+            ArrayBase::from(s),
+            Array2::from_shape_vec((n, n).f(), t).unwrap(),
+        ))
+    }
+}
+
+/// Calculate eigenvalues without eigenvectors
+pub trait EigVals {
+    type EigVal;
+    fn eigvals(&self) -> Result<Self::EigVal>;
+}
+
+impl<A, S> EigVals for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type EigVal = Array1<A::Complex>;
+
+    fn eigvals(&self) -> Result<Self::EigVal> {
+        let mut a = self.to_owned();
+        let (s, _) = A::eig(false, a.square_layout()?, a.as_allocated_mut()?)?;
+        Ok(ArrayBase::from(s))
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/eigh.rs.html b/src/ndarray_linalg/eigh.rs.html new file mode 100644 index 00000000..bf6cf1df --- /dev/null +++ b/src/ndarray_linalg/eigh.rs.html @@ -0,0 +1,580 @@ +eigh.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+
//! Eigendecomposition for Hermitian matrices.
+//!
+//! For a Hermitian matrix `A`, this solves the eigenvalue problem `A V = V D`
+//! for `D` and `V`, where `D` is the diagonal matrix of eigenvalues in
+//! ascending order and `V` is the orthonormal matrix of corresponding
+//! eigenvectors.
+//!
+//! For a pair of Hermitian matrices `A` and `B` where `B` is also positive
+//! definite, this solves the generalized eigenvalue problem `A V = B V D`,
+//! where `D` is the diagonal matrix of generalized eigenvalues in ascending
+//! order and `V` is the matrix of corresponding generalized eigenvectors. The
+//! matrix `V` is normalized such that `V^H B V = I`.
+//!
+//! # Example
+//!
+//! Find the eigendecomposition of a Hermitian (or real symmetric) matrix.
+//!
+//! ```
+//! use approx::assert_abs_diff_eq;
+//! use ndarray::{array, Array2};
+//! use ndarray_linalg::{Eigh, UPLO};
+//!
+//! let a: Array2<f64> = array![
+//!     [2., 1.],
+//!     [1., 2.],
+//! ];
+//! let (eigvals, eigvecs) = a.eigh(UPLO::Lower)?;
+//! assert_abs_diff_eq!(eigvals, array![1., 3.]);
+//! assert_abs_diff_eq!(
+//!     a.dot(&eigvecs),
+//!     eigvecs.dot(&Array2::from_diag(&eigvals)),
+//! );
+//! # Ok::<(), Box<dyn std::error::Error>>(())
+//! ```
+
+use ndarray::*;
+
+use crate::diagonal::*;
+use crate::error::*;
+use crate::layout::*;
+use crate::operator::LinearOperator;
+use crate::types::*;
+use crate::UPLO;
+
+/// Eigenvalue decomposition of Hermite matrix reference
+pub trait Eigh {
+    type EigVal;
+    type EigVec;
+    fn eigh(&self, uplo: UPLO) -> Result<(Self::EigVal, Self::EigVec)>;
+}
+
+/// Eigenvalue decomposition of mutable reference of Hermite matrix
+pub trait EighInplace {
+    type EigVal;
+    fn eigh_inplace(&mut self, uplo: UPLO) -> Result<(Self::EigVal, &mut Self)>;
+}
+
+/// Eigenvalue decomposition of Hermite matrix
+pub trait EighInto: Sized {
+    type EigVal;
+    fn eigh_into(self, uplo: UPLO) -> Result<(Self::EigVal, Self)>;
+}
+
+impl<A, S> EighInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+
+    fn eigh_into(mut self, uplo: UPLO) -> Result<(Self::EigVal, Self)> {
+        let (val, _) = self.eigh_inplace(uplo)?;
+        Ok((val, self))
+    }
+}
+
+impl<A, S, S2> EighInto for (ArrayBase<S, Ix2>, ArrayBase<S2, Ix2>)
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+    S2: DataMut<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+
+    fn eigh_into(mut self, uplo: UPLO) -> Result<(Self::EigVal, Self)> {
+        let (val, _) = self.eigh_inplace(uplo)?;
+        Ok((val, self))
+    }
+}
+
+impl<A, S> Eigh for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+    type EigVec = Array2<A>;
+
+    fn eigh(&self, uplo: UPLO) -> Result<(Self::EigVal, Self::EigVec)> {
+        let a = self.to_owned();
+        a.eigh_into(uplo)
+    }
+}
+
+impl<A, S, S2> Eigh for (ArrayBase<S, Ix2>, ArrayBase<S2, Ix2>)
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+    S2: Data<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+    type EigVec = (Array2<A>, Array2<A>);
+
+    fn eigh(&self, uplo: UPLO) -> Result<(Self::EigVal, Self::EigVec)> {
+        let (a, b) = (self.0.to_owned(), self.1.to_owned());
+        (a, b).eigh_into(uplo)
+    }
+}
+
+impl<A, S> EighInplace for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+
+    fn eigh_inplace(&mut self, uplo: UPLO) -> Result<(Self::EigVal, &mut Self)> {
+        let layout = self.square_layout()?;
+        // XXX Force layout to be Fortran (see #146)
+        match layout {
+            MatrixLayout::C { .. } => self.swap_axes(0, 1),
+            MatrixLayout::F { .. } => {}
+        }
+        let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
+        Ok((ArrayBase::from(s), self))
+    }
+}
+
+impl<A, S, S2> EighInplace for (ArrayBase<S, Ix2>, ArrayBase<S2, Ix2>)
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+    S2: DataMut<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+
+    /// Solves the generalized eigenvalue problem.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the shapes of the matrices are different.
+    fn eigh_inplace(&mut self, uplo: UPLO) -> Result<(Self::EigVal, &mut Self)> {
+        assert_eq!(
+            self.0.shape(),
+            self.1.shape(),
+            "The shapes of the matrices must be identical.",
+        );
+        let layout = self.0.square_layout()?;
+        // XXX Force layout to be Fortran (see #146)
+        match layout {
+            MatrixLayout::C { .. } => self.0.swap_axes(0, 1),
+            MatrixLayout::F { .. } => {}
+        }
+
+        let layout = self.1.square_layout()?;
+        match layout {
+            MatrixLayout::C { .. } => self.1.swap_axes(0, 1),
+            MatrixLayout::F { .. } => {}
+        }
+
+        let s = A::eigh_generalized(
+            true,
+            self.0.square_layout()?,
+            uplo,
+            self.0.as_allocated_mut()?,
+            self.1.as_allocated_mut()?,
+        )?;
+
+        Ok((ArrayBase::from(s), self))
+    }
+}
+
+/// Calculate eigenvalues without eigenvectors
+pub trait EigValsh {
+    type EigVal;
+    fn eigvalsh(&self, uplo: UPLO) -> Result<Self::EigVal>;
+}
+
+/// Calculate eigenvalues without eigenvectors
+pub trait EigValshInto {
+    type EigVal;
+    fn eigvalsh_into(self, uplo: UPLO) -> Result<Self::EigVal>;
+}
+
+/// Calculate eigenvalues without eigenvectors
+pub trait EigValshInplace {
+    type EigVal;
+    fn eigvalsh_inplace(&mut self, uplo: UPLO) -> Result<Self::EigVal>;
+}
+
+impl<A, S> EigValshInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+
+    fn eigvalsh_into(mut self, uplo: UPLO) -> Result<Self::EigVal> {
+        self.eigvalsh_inplace(uplo)
+    }
+}
+
+impl<A, S> EigValsh for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+
+    fn eigvalsh(&self, uplo: UPLO) -> Result<Self::EigVal> {
+        let a = self.to_owned();
+        a.eigvalsh_into(uplo)
+    }
+}
+
+impl<A, S> EigValshInplace for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type EigVal = Array1<A::Real>;
+
+    fn eigvalsh_inplace(&mut self, uplo: UPLO) -> Result<Self::EigVal> {
+        let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
+        Ok(ArrayBase::from(s))
+    }
+}
+
+/// Calculate symmetric square-root matrix using `eigh`
+pub trait SymmetricSqrt {
+    type Output;
+    fn ssqrt(&self, uplo: UPLO) -> Result<Self::Output>;
+}
+
+impl<A, S> SymmetricSqrt for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = Array2<A>;
+
+    fn ssqrt(&self, uplo: UPLO) -> Result<Self::Output> {
+        let a = self.to_owned();
+        a.ssqrt_into(uplo)
+    }
+}
+
+/// Calculate symmetric square-root matrix using `eigh`
+pub trait SymmetricSqrtInto {
+    type Output;
+    fn ssqrt_into(self, uplo: UPLO) -> Result<Self::Output>;
+}
+
+impl<A, S> SymmetricSqrtInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A> + DataOwned,
+{
+    type Output = Array2<A>;
+
+    fn ssqrt_into(self, uplo: UPLO) -> Result<Self::Output> {
+        let (e, v) = self.eigh_into(uplo)?;
+        let e_sqrt = Array::from_iter(e.iter().map(|r| Scalar::from_real(r.sqrt())));
+        let ev = e_sqrt.into_diagonal().apply2(&v.t());
+        Ok(v.apply2(&ev))
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/error.rs.html b/src/ndarray_linalg/error.rs.html new file mode 100644 index 00000000..24f29c09 --- /dev/null +++ b/src/ndarray_linalg/error.rs.html @@ -0,0 +1,102 @@ +error.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+
//! Define Errors
+
+use ndarray::{Ixs, ShapeError};
+use thiserror::Error;
+
+pub type Result<T> = ::std::result::Result<T, LinalgError>;
+
+/// Master Error type of this crate
+#[derive(Debug, Error)]
+pub enum LinalgError {
+    /// Matrix is not square
+    #[error("Not square: rows({}) != cols({})", rows, cols)]
+    NotSquare { rows: i32, cols: i32 },
+
+    /// LAPACK subroutine returns non-zero code
+    #[error(transparent)]
+    Lapack(#[from] lax::error::Error),
+
+    /// Strides of the array is not supported
+    #[error("invalid stride: s0={}, s1={}", s0, s1)]
+    InvalidStride { s0: Ixs, s1: Ixs },
+
+    /// Memory is not aligned continously
+    #[error("Memroy is not continously")]
+    MemoryNotCont,
+
+    /// Obj cannot be made from a (rows, cols) matrix
+    #[error("{} cannot be made from a ({}, {}) matrix", obj, rows, cols)]
+    NotStandardShape {
+        obj: &'static str,
+        rows: i32,
+        cols: i32,
+    },
+
+    /// Strides of the array is not supported
+    #[error(transparent)]
+    Shape(#[from] ShapeError),
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/generate.rs.html b/src/ndarray_linalg/generate.rs.html new file mode 100644 index 00000000..7b78dc0b --- /dev/null +++ b/src/ndarray_linalg/generate.rs.html @@ -0,0 +1,276 @@ +generate.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+
//! Generator functions for matrices
+
+use ndarray::*;
+use rand::prelude::*;
+
+use super::convert::*;
+use super::error::*;
+use super::qr::*;
+use super::types::*;
+
+/// Hermite conjugate matrix
+pub fn conjugate<A, Si, So>(a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
+where
+    A: Scalar,
+    Si: Data<Elem = A>,
+    So: DataOwned<Elem = A> + DataMut,
+{
+    let mut a: ArrayBase<So, Ix2> = replicate(&a.t());
+    for val in a.iter_mut() {
+        *val = val.conj();
+    }
+    a
+}
+
+/// Generate random array
+pub fn random<A, S, Sh, D>(sh: Sh) -> ArrayBase<S, D>
+where
+    A: Scalar,
+    S: DataOwned<Elem = A>,
+    D: Dimension,
+    Sh: ShapeBuilder<Dim = D>,
+{
+    let mut rng = thread_rng();
+    ArrayBase::from_shape_fn(sh, |_| A::rand(&mut rng))
+}
+
+/// Generate random unitary matrix using QR decomposition
+///
+/// Be sure that this it **NOT** a uniform distribution. Use it only for test purpose.
+pub fn random_unitary<A>(n: usize) -> Array2<A>
+where
+    A: Scalar + Lapack,
+{
+    let a: Array2<A> = random((n, n));
+    let (q, _r) = a.qr_into().unwrap();
+    q
+}
+
+/// Generate random regular matrix
+///
+/// Be sure that this it **NOT** a uniform distribution. Use it only for test purpose.
+pub fn random_regular<A>(n: usize) -> Array2<A>
+where
+    A: Scalar + Lapack,
+{
+    let a: Array2<A> = random((n, n));
+    let (q, mut r) = a.qr_into().unwrap();
+    for i in 0..n {
+        r[(i, i)] = A::one() + A::from_real(r[(i, i)].abs());
+    }
+    q.dot(&r)
+}
+
+/// Random Hermite matrix
+pub fn random_hermite<A, S>(n: usize) -> ArrayBase<S, Ix2>
+where
+    A: Scalar,
+    S: DataOwned<Elem = A> + DataMut,
+{
+    let mut a: ArrayBase<S, Ix2> = random((n, n));
+    for i in 0..n {
+        a[(i, i)] = a[(i, i)] + a[(i, i)].conj();
+        for j in (i + 1)..n {
+            a[(i, j)] = a[(j, i)].conj();
+        }
+    }
+    a
+}
+
+/// Random Hermite Positive-definite matrix
+///
+/// - Eigenvalue of matrix must be larger than 1 (thus non-singular)
+///
+pub fn random_hpd<A, S>(n: usize) -> ArrayBase<S, Ix2>
+where
+    A: Scalar,
+    S: DataOwned<Elem = A> + DataMut,
+{
+    let a: Array2<A> = random((n, n));
+    let ah: Array2<A> = conjugate(&a);
+    ArrayBase::eye(n) + &ah.dot(&a)
+}
+
+/// construct matrix from diag
+pub fn from_diag<A>(d: &[A]) -> Array2<A>
+where
+    A: Scalar,
+{
+    let n = d.len();
+    let mut e = Array::zeros((n, n));
+    for i in 0..n {
+        e[(i, i)] = d[i];
+    }
+    e
+}
+
+/// stack vectors into matrix horizontally
+pub fn hstack<A, S>(xs: &[ArrayBase<S, Ix1>]) -> Result<Array<A, Ix2>>
+where
+    A: Scalar,
+    S: Data<Elem = A>,
+{
+    let views: Vec<_> = xs.iter().map(|x| x.view()).collect();
+    stack(Axis(1), &views).map_err(Into::into)
+}
+
+/// stack vectors into matrix vertically
+pub fn vstack<A, S>(xs: &[ArrayBase<S, Ix1>]) -> Result<Array<A, Ix2>>
+where
+    A: Scalar,
+    S: Data<Elem = A>,
+{
+    let views: Vec<_> = xs.iter().map(|x| x.view()).collect();
+    stack(Axis(0), &views).map_err(Into::into)
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/inner.rs.html b/src/ndarray_linalg/inner.rs.html new file mode 100644 index 00000000..f09cf384 --- /dev/null +++ b/src/ndarray_linalg/inner.rs.html @@ -0,0 +1,90 @@ +inner.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+
use crate::types::*;
+use ndarray::*;
+
+/// Inner Product
+///
+/// Differenct from `Dot` trait, this take complex conjugate of `self` elements
+///
+pub trait InnerProduct {
+    type Elem: Scalar;
+
+    /// Inner product `(self.conjugate, rhs)
+    fn inner<S>(&self, rhs: &ArrayBase<S, Ix1>) -> Self::Elem
+    where
+        S: Data<Elem = Self::Elem>;
+}
+
+impl<A, S> InnerProduct for ArrayBase<S, Ix1>
+where
+    A: Scalar,
+    S: Data<Elem = A>,
+{
+    type Elem = A;
+    fn inner<St: Data<Elem = A>>(&self, rhs: &ArrayBase<St, Ix1>) -> A {
+        assert_eq!(self.len(), rhs.len());
+        Zip::from(self)
+            .and(rhs)
+            .fold_while(A::zero(), |acc, s, r| {
+                FoldWhile::Continue(acc + s.conj() * *r)
+            })
+            .into_inner()
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/krylov/arnoldi.rs.html b/src/ndarray_linalg/krylov/arnoldi.rs.html new file mode 100644 index 00000000..7a3c54c3 --- /dev/null +++ b/src/ndarray_linalg/krylov/arnoldi.rs.html @@ -0,0 +1,276 @@ +arnoldi.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+
//! Arnoldi iteration
+
+use super::*;
+use crate::{norm::Norm, operator::LinearOperator};
+use num_traits::One;
+use std::iter::*;
+
+/// Execute Arnoldi iteration as Rust iterator
+///
+/// - [Arnoldi iteration - Wikipedia](https://en.wikipedia.org/wiki/Arnoldi_iteration)
+///
+pub struct Arnoldi<A, S, F, Ortho>
+where
+    A: Scalar,
+    S: DataMut<Elem = A>,
+    F: LinearOperator<Elem = A>,
+    Ortho: Orthogonalizer<Elem = A>,
+{
+    a: F,
+    /// Next vector (normalized `|v|=1`)
+    v: ArrayBase<S, Ix1>,
+    /// Orthogonalizer
+    ortho: Ortho,
+    /// Coefficients to be composed into H-matrix
+    h: Vec<Array1<A>>,
+}
+
+impl<A, S, F, Ortho> Arnoldi<A, S, F, Ortho>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+    F: LinearOperator<Elem = A>,
+    Ortho: Orthogonalizer<Elem = A>,
+{
+    /// Create an Arnoldi iterator from any linear operator `a`
+    pub fn new(a: F, mut v: ArrayBase<S, Ix1>, mut ortho: Ortho) -> Self {
+        assert_eq!(ortho.len(), 0);
+        assert!(ortho.tolerance() < One::one());
+        // normalize before append because |v| may be smaller than ortho.tolerance()
+        let norm = v.norm_l2();
+        azip!((v in &mut v)  *v = v.div_real(norm));
+        ortho.append(v.view());
+        Arnoldi {
+            a,
+            v,
+            ortho,
+            h: Vec::new(),
+        }
+    }
+
+    /// Dimension of Krylov subspace
+    pub fn dim(&self) -> usize {
+        self.ortho.len()
+    }
+
+    /// Iterate until convergent
+    pub fn complete(mut self) -> (Q<A>, H<A>) {
+        for _ in &mut self {} // execute iteration until convergent
+        let q = self.ortho.get_q();
+        let n = self.h.len();
+        let mut h = Array2::zeros((n, n).f());
+        for (i, hc) in self.h.iter().enumerate() {
+            let m = std::cmp::min(n, i + 2);
+            for j in 0..m {
+                h[(j, i)] = hc[j];
+            }
+        }
+        (q, h)
+    }
+}
+
+impl<A, S, F, Ortho> Iterator for Arnoldi<A, S, F, Ortho>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+    F: LinearOperator<Elem = A>,
+    Ortho: Orthogonalizer<Elem = A>,
+{
+    type Item = Array1<A>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.a.apply_mut(&mut self.v);
+        let result = self.ortho.div_append(&mut self.v);
+        let norm = self.v.norm_l2();
+        azip!((v in &mut self.v) *v = v.div_real(norm));
+        match result {
+            AppendResult::Added(coef) => {
+                self.h.push(coef.clone());
+                Some(coef)
+            }
+            AppendResult::Dependent(coef) => {
+                self.h.push(coef);
+                None
+            }
+        }
+    }
+}
+
+/// Utility to execute Arnoldi iteration with Householder reflection
+pub fn arnoldi_householder<A, S>(
+    a: impl LinearOperator<Elem = A>,
+    v: ArrayBase<S, Ix1>,
+    tol: A::Real,
+) -> (Q<A>, H<A>)
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    let householder = Householder::new(v.len(), tol);
+    Arnoldi::new(a, v, householder).complete()
+}
+
+/// Utility to execute Arnoldi iteration with modified Gram-Schmit orthogonalizer
+pub fn arnoldi_mgs<A, S>(
+    a: impl LinearOperator<Elem = A>,
+    v: ArrayBase<S, Ix1>,
+    tol: A::Real,
+) -> (Q<A>, H<A>)
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    let mgs = MGS::new(v.len(), tol);
+    Arnoldi::new(a, v, mgs).complete()
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/krylov/householder.rs.html b/src/ndarray_linalg/krylov/householder.rs.html new file mode 100644 index 00000000..e0005ee1 --- /dev/null +++ b/src/ndarray_linalg/krylov/householder.rs.html @@ -0,0 +1,520 @@ +householder.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+
//! Householder reflection
+//!
+//! - [Householder transformation - Wikipedia](https://en.wikipedia.org/wiki/Householder_transformation)
+//!
+
+use super::*;
+use crate::{inner::*, norm::*};
+use num_traits::One;
+
+/// Calc a reflactor `w` from a vector `x`
+pub fn calc_reflector<A, S>(x: &mut ArrayBase<S, Ix1>)
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    assert!(!x.is_empty());
+    let norm = x.norm_l2();
+    let alpha = -x[0].mul_real(norm / x[0].abs());
+    x[0] -= alpha;
+    let inv_rev_norm = A::Real::one() / x.norm_l2();
+    azip!((a in x) *a = a.mul_real(inv_rev_norm));
+}
+
+/// Take a reflection `P = I - 2ww^T`
+///
+/// Panic
+/// ------
+/// - if the size of `w` and `a` mismaches
+pub fn reflect<A, S1, S2>(w: &ArrayBase<S1, Ix1>, a: &mut ArrayBase<S2, Ix1>)
+where
+    A: Scalar + Lapack,
+    S1: Data<Elem = A>,
+    S2: DataMut<Elem = A>,
+{
+    assert_eq!(w.len(), a.len());
+    let n = a.len();
+    let c = A::from(2.0).unwrap() * w.inner(a);
+    for l in 0..n {
+        a[l] -= c * w[l];
+    }
+}
+
+/// Iterative orthogonalizer using Householder reflection
+#[derive(Debug, Clone)]
+pub struct Householder<A: Scalar> {
+    /// Dimension of orthogonalizer
+    dim: usize,
+
+    /// Store Householder reflector.
+    ///
+    /// The coefficient is copied into another array, and this does not contain
+    v: Vec<Array1<A>>,
+
+    /// Tolerance
+    tol: A::Real,
+}
+
+impl<A: Scalar + Lapack> Householder<A> {
+    /// Create a new orthogonalizer
+    pub fn new(dim: usize, tol: A::Real) -> Self {
+        Householder {
+            dim,
+            v: Vec::new(),
+            tol,
+        }
+    }
+
+    /// Take a Reflection `P = I - 2ww^T`
+    fn fundamental_reflection<S>(&self, k: usize, a: &mut ArrayBase<S, Ix1>)
+    where
+        S: DataMut<Elem = A>,
+    {
+        assert!(k < self.v.len());
+        assert_eq!(
+            a.len(),
+            self.dim,
+            "Input array size mismaches to the dimension"
+        );
+        reflect(&self.v[k].slice(s![k..]), &mut a.slice_mut(s![k..]));
+    }
+
+    /// Take forward reflection `P = P_l ... P_1`
+    pub fn forward_reflection<S>(&self, a: &mut ArrayBase<S, Ix1>)
+    where
+        S: DataMut<Elem = A>,
+    {
+        assert!(a.len() == self.dim);
+        let l = self.v.len();
+        for k in 0..l {
+            self.fundamental_reflection(k, a);
+        }
+    }
+
+    /// Take backward reflection `P = P_1 ... P_l`
+    pub fn backward_reflection<S>(&self, a: &mut ArrayBase<S, Ix1>)
+    where
+        S: DataMut<Elem = A>,
+    {
+        assert!(a.len() == self.dim);
+        let l = self.v.len();
+        for k in (0..l).rev() {
+            self.fundamental_reflection(k, a);
+        }
+    }
+
+    /// Compose coefficients array using reflected vector
+    fn compose_coefficients<S>(&self, a: &ArrayBase<S, Ix1>) -> Coefficients<A>
+    where
+        S: Data<Elem = A>,
+    {
+        let k = self.len();
+        let res = a.slice(s![k..]).norm_l2();
+        let mut c = Array1::zeros(k + 1);
+        azip!((c in c.slice_mut(s![..k]), &a in a.slice(s![..k])) *c = a);
+        if k < a.len() {
+            let ak = a[k];
+            c[k] = -ak.mul_real(res / ak.abs());
+        } else {
+            c[k] = A::from_real(res);
+        }
+        c
+    }
+
+    /// Construct the residual vector from reflected vector
+    fn construct_residual<S>(&self, a: &mut ArrayBase<S, Ix1>)
+    where
+        S: DataMut<Elem = A>,
+    {
+        let k = self.len();
+        azip!((a in a.slice_mut(s![..k])) *a = A::zero());
+        self.backward_reflection(a);
+    }
+}
+
+impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
+    type Elem = A;
+
+    fn dim(&self) -> usize {
+        self.dim
+    }
+
+    fn len(&self) -> usize {
+        self.v.len()
+    }
+
+    fn tolerance(&self) -> A::Real {
+        self.tol
+    }
+
+    fn decompose<S>(&self, a: &mut ArrayBase<S, Ix1>) -> Array1<A>
+    where
+        S: DataMut<Elem = A>,
+    {
+        self.forward_reflection(a);
+        let coef = self.compose_coefficients(a);
+        self.construct_residual(a);
+        coef
+    }
+
+    fn coeff<S>(&self, a: ArrayBase<S, Ix1>) -> Array1<A>
+    where
+        S: Data<Elem = A>,
+    {
+        let mut a = a.into_owned();
+        self.forward_reflection(&mut a);
+        self.compose_coefficients(&a)
+    }
+
+    fn div_append<S>(&mut self, a: &mut ArrayBase<S, Ix1>) -> AppendResult<A>
+    where
+        S: DataMut<Elem = A>,
+    {
+        assert_eq!(a.len(), self.dim);
+        let k = self.len();
+        self.forward_reflection(a);
+        let coef = self.compose_coefficients(a);
+        if coef[k].abs() < self.tol {
+            return AppendResult::Dependent(coef);
+        }
+        calc_reflector(&mut a.slice_mut(s![k..]));
+        self.v.push(a.to_owned());
+        self.construct_residual(a);
+        AppendResult::Added(coef)
+    }
+
+    fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> AppendResult<A>
+    where
+        S: Data<Elem = A>,
+    {
+        assert_eq!(a.len(), self.dim);
+        let mut a = a.into_owned();
+        let k = self.len();
+        self.forward_reflection(&mut a);
+        let coef = self.compose_coefficients(&a);
+        if coef[k].abs() < self.tol {
+            return AppendResult::Dependent(coef);
+        }
+        calc_reflector(&mut a.slice_mut(s![k..]));
+        self.v.push(a.to_owned());
+        AppendResult::Added(coef)
+    }
+
+    fn get_q(&self) -> Q<A> {
+        assert!(self.len() > 0);
+        let mut a = Array::zeros((self.dim(), self.len()));
+        for (i, mut col) in a.axis_iter_mut(Axis(1)).enumerate() {
+            col[i] = A::one();
+            self.backward_reflection(&mut col);
+        }
+        a
+    }
+}
+
+/// Online QR decomposition using Householder reflection
+pub fn householder<A, S>(
+    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
+    dim: usize,
+    rtol: A::Real,
+    strategy: Strategy,
+) -> (Q<A>, R<A>)
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    let h = Householder::new(dim, rtol);
+    qr(iter, h, strategy)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::assert::*;
+    use num_traits::Zero;
+
+    #[test]
+    fn check_reflector() {
+        let mut a = array![c64::new(1.0, 1.0), c64::new(1.0, 0.0), c64::new(0.0, 1.0)];
+        let mut w = a.clone();
+        calc_reflector(&mut w);
+        reflect(&w, &mut a);
+        close_l2(
+            &a,
+            &array![-c64::new(2.0.sqrt(), 2.0.sqrt()), c64::zero(), c64::zero()],
+            1e-9,
+        );
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/krylov/mgs.rs.html b/src/ndarray_linalg/krylov/mgs.rs.html new file mode 100644 index 00000000..8c1bbadd --- /dev/null +++ b/src/ndarray_linalg/krylov/mgs.rs.html @@ -0,0 +1,254 @@ +mgs.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+
//! Modified Gram-Schmit orthogonalizer
+
+use super::*;
+use crate::{generate::*, inner::*, norm::Norm};
+
+/// Iterative orthogonalizer using modified Gram-Schmit procedure
+#[derive(Debug, Clone)]
+pub struct MGS<A: Scalar> {
+    /// Dimension of base space
+    dim: usize,
+
+    /// Basis of spanned space
+    q: Vec<Array1<A>>,
+
+    /// Tolerance
+    tol: A::Real,
+}
+
+impl<A: Scalar + Lapack> MGS<A> {
+    /// Create an empty orthogonalizer
+    pub fn new(dim: usize, tol: A::Real) -> Self {
+        Self {
+            dim,
+            q: Vec::new(),
+            tol,
+        }
+    }
+}
+
+impl<A: Scalar + Lapack> Orthogonalizer for MGS<A> {
+    type Elem = A;
+
+    fn dim(&self) -> usize {
+        self.dim
+    }
+
+    fn len(&self) -> usize {
+        self.q.len()
+    }
+
+    fn tolerance(&self) -> A::Real {
+        self.tol
+    }
+
+    fn decompose<S>(&self, a: &mut ArrayBase<S, Ix1>) -> Array1<A>
+    where
+        S: DataMut<Elem = A>,
+    {
+        assert_eq!(a.len(), self.dim());
+        let mut coef = Array1::zeros(self.len() + 1);
+        for i in 0..self.len() {
+            let q = &self.q[i];
+            let c = q.inner(a);
+            azip!((a in &mut *a, &q in q) *a -= c * q);
+            coef[i] = c;
+        }
+        let nrm = a.norm_l2();
+        coef[self.len()] = A::from_real(nrm);
+        coef
+    }
+
+    fn coeff<S>(&self, a: ArrayBase<S, Ix1>) -> Array1<A>
+    where
+        A: Lapack,
+        S: Data<Elem = A>,
+    {
+        let mut a = a.into_owned();
+        self.decompose(&mut a)
+    }
+
+    fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> AppendResult<A>
+    where
+        A: Lapack,
+        S: Data<Elem = A>,
+    {
+        let mut a = a.into_owned();
+        self.div_append(&mut a)
+    }
+
+    fn div_append<S>(&mut self, a: &mut ArrayBase<S, Ix1>) -> AppendResult<A>
+    where
+        A: Lapack,
+        S: DataMut<Elem = A>,
+    {
+        let coef = self.decompose(a);
+        let nrm = coef[coef.len() - 1].re();
+        if nrm < self.tol {
+            // Linearly dependent
+            return AppendResult::Dependent(coef);
+        }
+        azip!((a in &mut *a) *a /= A::from_real(nrm));
+        self.q.push(a.to_owned());
+        AppendResult::Added(coef)
+    }
+
+    fn get_q(&self) -> Q<A> {
+        hstack(&self.q).unwrap()
+    }
+}
+
+/// Online QR decomposition using modified Gram-Schmit algorithm
+pub fn mgs<A, S>(
+    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
+    dim: usize,
+    rtol: A::Real,
+    strategy: Strategy,
+) -> (Q<A>, R<A>)
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    let mgs = MGS::new(dim, rtol);
+    qr(iter, mgs, strategy)
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/krylov/mod.rs.html b/src/ndarray_linalg/krylov/mod.rs.html new file mode 100644 index 00000000..ff3a6079 --- /dev/null +++ b/src/ndarray_linalg/krylov/mod.rs.html @@ -0,0 +1,448 @@ +mod.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+
//! Krylov subspace methods
+
+use crate::types::*;
+use ndarray::*;
+
+pub mod arnoldi;
+pub mod householder;
+pub mod mgs;
+
+pub use arnoldi::{arnoldi_householder, arnoldi_mgs, Arnoldi};
+pub use householder::{householder, Householder};
+pub use mgs::{mgs, MGS};
+
+/// Q-matrix
+///
+/// - Maybe **NOT** square
+/// - Unitary for existing columns
+///
+pub type Q<A> = Array2<A>;
+
+/// R-matrix
+///
+/// - Maybe **NOT** square
+/// - Upper triangle
+///
+pub type R<A> = Array2<A>;
+
+/// H-matrix
+///
+/// - Maybe **NOT** square
+/// - Hessenberg matrix
+///
+pub type H<A> = Array2<A>;
+
+/// Array type for coefficients to the current basis
+///
+/// - The length must be `self.len() + 1`
+/// - Last component is the residual norm
+///
+pub type Coefficients<A> = Array1<A>;
+
+/// Trait for creating orthogonal basis from iterator of arrays
+///
+/// Panic
+/// -------
+/// - if the size of the input array mismatches to the dimension
+///
+/// Example
+/// -------
+///
+/// ```rust
+/// # use ndarray::*;
+/// # use ndarray_linalg::{krylov::*, *};
+/// let mut mgs = MGS::new(3, 1e-9);
+/// let coef = mgs.append(array![0.0, 1.0, 0.0]).into_coeff();
+/// close_l2(&coef, &array![1.0], 1e-9);
+///
+/// let coef = mgs.append(array![1.0, 1.0, 0.0]).into_coeff();
+/// close_l2(&coef, &array![1.0, 1.0], 1e-9);
+///
+/// // Fail if the vector is linearly dependent
+/// assert!(mgs.append(array![1.0, 2.0, 0.0]).is_dependent());
+///
+/// // You can get coefficients of dependent vector
+/// if let AppendResult::Dependent(coef) = mgs.append(array![1.0, 2.0, 0.0]) {
+///     close_l2(&coef, &array![2.0, 1.0, 0.0], 1e-9);
+/// }
+/// ```
+pub trait Orthogonalizer {
+    type Elem: Scalar;
+
+    /// Dimension of input array
+    fn dim(&self) -> usize;
+
+    /// Number of cached basis
+    fn len(&self) -> usize;
+
+    /// check if the basis spans entire space
+    fn is_full(&self) -> bool {
+        self.len() == self.dim()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    fn tolerance(&self) -> <Self::Elem as Scalar>::Real;
+
+    /// Decompose given vector into the span of current basis and
+    /// its tangent space
+    ///
+    /// - `a` becomes the tangent vector
+    /// - The Coefficients to the current basis is returned.
+    ///
+    fn decompose<S>(&self, a: &mut ArrayBase<S, Ix1>) -> Coefficients<Self::Elem>
+    where
+        S: DataMut<Elem = Self::Elem>;
+
+    /// Calculate the coefficient to the current basis basis
+    ///
+    /// - This will be faster than `decompose` because the construction of the residual vector may
+    ///   requires more Calculation
+    ///
+    fn coeff<S>(&self, a: ArrayBase<S, Ix1>) -> Coefficients<Self::Elem>
+    where
+        S: Data<Elem = Self::Elem>;
+
+    /// Add new vector if the residual is larger than relative tolerance
+    fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> AppendResult<Self::Elem>
+    where
+        S: Data<Elem = Self::Elem>;
+
+    /// Add new vector if the residual is larger than relative tolerance,
+    /// and return the residual vector
+    fn div_append<S>(&mut self, a: &mut ArrayBase<S, Ix1>) -> AppendResult<Self::Elem>
+    where
+        S: DataMut<Elem = Self::Elem>;
+
+    /// Get Q-matrix of generated basis
+    fn get_q(&self) -> Q<Self::Elem>;
+}
+
+pub enum AppendResult<A> {
+    Added(Coefficients<A>),
+    Dependent(Coefficients<A>),
+}
+
+impl<A: Scalar> AppendResult<A> {
+    pub fn into_coeff(self) -> Coefficients<A> {
+        match self {
+            AppendResult::Added(c) => c,
+            AppendResult::Dependent(c) => c,
+        }
+    }
+
+    pub fn is_dependent(&self) -> bool {
+        match self {
+            AppendResult::Added(_) => false,
+            AppendResult::Dependent(_) => true,
+        }
+    }
+
+    pub fn coeff(&self) -> &Coefficients<A> {
+        match self {
+            AppendResult::Added(c) => c,
+            AppendResult::Dependent(c) => c,
+        }
+    }
+
+    pub fn residual_norm(&self) -> A::Real {
+        let c = self.coeff();
+        c[c.len() - 1].abs()
+    }
+}
+
+/// Strategy for linearly dependent vectors appearing in iterative QR decomposition
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum Strategy {
+    /// Terminate iteration if dependent vector comes
+    Terminate,
+
+    /// Skip dependent vector
+    Skip,
+
+    /// Orthogonalize dependent vector without adding to Q,
+    /// i.e. R must be non-square like following:
+    ///
+    /// ```text
+    /// x x x x x
+    /// 0 x x x x
+    /// 0 0 0 x x
+    /// 0 0 0 0 x
+    /// ```
+    Full,
+}
+
+/// Online QR decomposition using arbitrary orthogonalizer
+pub fn qr<A, S>(
+    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
+    mut ortho: impl Orthogonalizer<Elem = A>,
+    strategy: Strategy,
+) -> (Q<A>, R<A>)
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    assert_eq!(ortho.len(), 0);
+
+    let mut coefs = Vec::new();
+    for a in iter {
+        match ortho.append(a.into_owned()) {
+            AppendResult::Added(coef) => coefs.push(coef),
+            AppendResult::Dependent(coef) => match strategy {
+                Strategy::Terminate => break,
+                Strategy::Skip => continue,
+                Strategy::Full => coefs.push(coef),
+            },
+        }
+    }
+    let n = ortho.len();
+    let m = coefs.len();
+    let mut r = Array2::zeros((n, m).f());
+    for j in 0..m {
+        for i in 0..n {
+            if i < coefs[j].len() {
+                r[(i, j)] = coefs[j][i];
+            }
+        }
+    }
+    (ortho.get_q(), r)
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/layout.rs.html b/src/ndarray_linalg/layout.rs.html new file mode 100644 index 00000000..6297147b --- /dev/null +++ b/src/ndarray_linalg/layout.rs.html @@ -0,0 +1,192 @@ +layout.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+
//! Convert ndarray into LAPACK-compatible matrix format
+
+use super::error::*;
+use ndarray::*;
+
+pub use lax::layout::MatrixLayout;
+
+pub trait AllocatedArray {
+    type Elem;
+    fn layout(&self) -> Result<MatrixLayout>;
+    fn square_layout(&self) -> Result<MatrixLayout>;
+    /// Returns Ok iff the matrix is square (without computing the layout).
+    fn ensure_square(&self) -> Result<()>;
+    fn as_allocated(&self) -> Result<&[Self::Elem]>;
+}
+
+pub trait AllocatedArrayMut: AllocatedArray {
+    fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
+}
+
+impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
+where
+    S: Data<Elem = A>,
+{
+    type Elem = A;
+
+    fn layout(&self) -> Result<MatrixLayout> {
+        let shape = self.shape();
+        let strides = self.strides();
+        if shape[0] == strides[1] as usize {
+            return Ok(MatrixLayout::F {
+                col: self.ncols() as i32,
+                lda: self.nrows() as i32,
+            });
+        }
+        if shape[1] == strides[0] as usize {
+            return Ok(MatrixLayout::C {
+                row: self.nrows() as i32,
+                lda: self.ncols() as i32,
+            });
+        }
+        Err(LinalgError::InvalidStride {
+            s0: strides[0],
+            s1: strides[1],
+        })
+    }
+
+    fn square_layout(&self) -> Result<MatrixLayout> {
+        let l = self.layout()?;
+        let (n, m) = l.size();
+        if n == m {
+            Ok(l)
+        } else {
+            Err(LinalgError::NotSquare { rows: n, cols: m })
+        }
+    }
+
+    fn ensure_square(&self) -> Result<()> {
+        if self.is_square() {
+            Ok(())
+        } else {
+            Err(LinalgError::NotSquare {
+                rows: self.nrows() as i32,
+                cols: self.ncols() as i32,
+            })
+        }
+    }
+
+    fn as_allocated(&self) -> Result<&[A]> {
+        self.as_slice_memory_order()
+            .ok_or(LinalgError::MemoryNotCont)
+    }
+}
+
+impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix2>
+where
+    S: DataMut<Elem = A>,
+{
+    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
+        self.as_slice_memory_order_mut()
+            .ok_or(LinalgError::MemoryNotCont)
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/least_squares.rs.html b/src/ndarray_linalg/least_squares.rs.html new file mode 100644 index 00000000..33d958c8 --- /dev/null +++ b/src/ndarray_linalg/least_squares.rs.html @@ -0,0 +1,1224 @@ +least_squares.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+
//! # Least Squares
+//!
+//! Compute a least-squares solution to the equation Ax = b.
+//! Compute a vector x such that the 2-norm ``|b - A x|`` is minimized.
+//!
+//! Finding the least squares solutions is implemented as traits, meaning
+//! that to solve `A x = b` for a matrix `A` and a RHS `b`, we call
+//! `let result = A.least_squares(&b);`. This returns a `result` of
+//! type `LeastSquaresResult`, the solution for the least square problem
+//! is in `result.solution`.
+//!
+//! There are three traits, `LeastSquaresSvd` with the method `least_squares`,
+//! which operates on immutable references, `LeastSquaresInto` with the method
+//! `least_squares_into`, which takes ownership over both the array `A` and the
+//! RHS `b` and `LeastSquaresSvdInPlace` with the method `least_squares_in_place`,
+//! which operates on mutable references for `A` and `b` and destroys these when
+//! solving the least squares problem. `LeastSquaresSvdInto` and
+//! `LeastSquaresSvdInPlace` avoid an extra allocation for `A` and `b` which
+//! `LeastSquaresSvd` has do perform to preserve the values in `A` and `b`.
+//!
+//! All methods use the Lapacke family of methods `*gelsd` which solves the least
+//! squares problem using the SVD with a divide-and-conquer strategy.
+//!
+//! The traits are implemented for value types `f32`, `f64`, `c32` and `c64`
+//! and vector or matrix right-hand-sides (`ArrayBase<S, Ix1>` or `ArrayBase<S, Ix2>`).
+//!
+//! ## Example
+//! ```rust
+//! use approx::AbsDiffEq; // for abs_diff_eq
+//! use ndarray::{array, Array1, Array2};
+//! use ndarray_linalg::{LeastSquaresSvd, LeastSquaresSvdInto, LeastSquaresSvdInPlace};
+//!
+//! let a: Array2<f64> = array![
+//!     [1., 1., 1.],
+//!     [2., 3., 4.],
+//!     [3., 5., 2.],
+//!     [4., 2., 5.],
+//!     [5., 4., 3.]
+//! ];
+//! // solving for a single right-hand side
+//! let b: Array1<f64> = array![-10., 12., 14., 16., 18.];
+//! let expected: Array1<f64> = array![2., 1., 1.];
+//! let result = a.least_squares(&b).unwrap();
+//! assert!(result.solution.abs_diff_eq(&expected, 1e-12));
+//!
+//! // solving for two right-hand sides at once
+//! let b_2: Array2<f64> =
+//!     array![[-10., -3.], [12., 14.], [14., 12.], [16., 16.], [18., 16.]];
+//! let expected_2: Array2<f64> = array![[2., 1.], [1., 1.], [1., 2.]];
+//! let result_2 = a.least_squares(&b_2).unwrap();
+//! assert!(result_2.solution.abs_diff_eq(&expected_2, 1e-12));
+//!
+//! // using `least_squares_in_place` which overwrites its arguments
+//! let mut a_3 = a.clone();
+//! let mut b_3 = b.clone();
+//! let result_3 = a_3.least_squares_in_place(&mut b_3).unwrap();
+//!
+//! // using `least_squares_into` which consumes its arguments
+//! let result_4 = a.least_squares_into(b).unwrap();
+//! // `a` and `b` have been moved, no longer valid
+//! ```
+
+use lax::*;
+use ndarray::*;
+
+use crate::error::*;
+use crate::layout::*;
+use crate::types::*;
+
+/// Result of a LeastSquares computation
+///
+/// Takes two type parameters, `E`, the element type of the matrix
+/// (one of `f32`, `f64`, `c32` or `c64`) and `I`, the dimension of
+/// b in the equation `Ax = b` (one of `Ix1` or `Ix2`). If `I` is `Ix1`,
+/// the  right-hand-side (RHS) is a `n x 1` column vector and the solution
+/// is a `m x 1` column vector. If `I` is `Ix2`, the RHS is a `n x k` matrix
+/// (which can be seen as solving `Ax = b` k times for different b) and
+/// the solution is a `m x k` matrix.
+#[derive(Debug, Clone)]
+pub struct LeastSquaresResult<E: Scalar, I: Dimension> {
+    /// The singular values of the matrix A in `Ax = b`
+    pub singular_values: Array1<E::Real>,
+    /// The solution vector or matrix `x` which is the best
+    /// solution to `Ax = b`, i.e. minimizing the 2-norm `||b - Ax||`
+    pub solution: Array<E, I>,
+    /// The rank of the matrix A in `Ax = b`
+    pub rank: i32,
+    /// If n < m and rank(A) == n, the sum of squares
+    /// If b is a (m x 1) vector, this is a 0-dimensional array (single value)
+    /// If b is a (m x k) matrix, this is a (k x 1) column vector
+    pub residual_sum_of_squares: Option<Array<E::Real, I::Smaller>>,
+}
+/// Solve least squares for immutable references
+pub trait LeastSquaresSvd<D, E, I>
+where
+    D: Data<Elem = E>,
+    E: Scalar + Lapack,
+    I: Dimension,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(&rhs)`. `A` and `rhs`
+    /// are unchanged.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares(&self, rhs: &ArrayBase<D, I>) -> Result<LeastSquaresResult<E, I>>;
+}
+
+/// Solve least squares for owned matrices
+pub trait LeastSquaresSvdInto<D, E, I>
+where
+    D: Data<Elem = E>,
+    E: Scalar + Lapack,
+    I: Dimension,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(rhs)`, consuming both `A`
+    /// and `rhs`. This uses the memory location of `A` and
+    /// `rhs`, which avoids some extra memory allocations.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares_into(self, rhs: ArrayBase<D, I>) -> Result<LeastSquaresResult<E, I>>;
+}
+
+/// Solve least squares for mutable references, overwriting
+/// the input fields in the process
+pub trait LeastSquaresSvdInPlace<D, E, I>
+where
+    D: Data<Elem = E>,
+    E: Scalar + Lapack,
+    I: Dimension,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(&mut rhs)`, overwriting both `A`
+    /// and `rhs`. This uses the memory location of `A` and
+    /// `rhs`, which avoids some extra memory allocations.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares_in_place(
+        &mut self,
+        rhs: &mut ArrayBase<D, I>,
+    ) -> Result<LeastSquaresResult<E, I>>;
+}
+
+/// Solve least squares for immutable references and a single
+/// column vector as a right-hand side.
+/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any
+/// valid representation for `ArrayBase` (over `E`).
+impl<E, D1, D2> LeastSquaresSvd<D2, E, Ix1> for ArrayBase<D1, Ix2>
+where
+    E: Scalar + Lapack,
+    D1: Data<Elem = E>,
+    D2: Data<Elem = E>,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(&rhs)`, where `rhs` is a
+    /// single column vector. `A` and `rhs` are unchanged.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares(&self, rhs: &ArrayBase<D2, Ix1>) -> Result<LeastSquaresResult<E, Ix1>> {
+        let a = self.to_owned();
+        let b = rhs.to_owned();
+        a.least_squares_into(b)
+    }
+}
+
+/// Solve least squares for immutable references and matrix
+/// (=mulitipe vectors) as a right-hand side.
+/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any
+/// valid representation for `ArrayBase` (over `E`).
+impl<E, D1, D2> LeastSquaresSvd<D2, E, Ix2> for ArrayBase<D1, Ix2>
+where
+    E: Scalar + Lapack,
+    D1: Data<Elem = E>,
+    D2: Data<Elem = E>,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(&rhs)`, where `rhs` is
+    /// matrix. `A` and `rhs` are unchanged.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares(&self, rhs: &ArrayBase<D2, Ix2>) -> Result<LeastSquaresResult<E, Ix2>> {
+        let a = self.to_owned();
+        let b = rhs.to_owned();
+        a.least_squares_into(b)
+    }
+}
+
+/// Solve least squares for owned values and a single
+/// column vector as a right-hand side. The matrix and the RHS
+/// vector are consumed.
+///
+/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D` can be any
+/// valid representation for `ArrayBase`.
+impl<E, D1, D2> LeastSquaresSvdInto<D2, E, Ix1> for ArrayBase<D1, Ix2>
+where
+    E: Scalar + Lapack,
+    D1: DataMut<Elem = E>,
+    D2: DataMut<Elem = E>,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(rhs)`, where `rhs` is a
+    /// single column vector. `A` and `rhs` are consumed.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares_into(
+        mut self,
+        mut rhs: ArrayBase<D2, Ix1>,
+    ) -> Result<LeastSquaresResult<E, Ix1>> {
+        self.least_squares_in_place(&mut rhs)
+    }
+}
+
+/// Solve least squares for owned values and a matrix
+/// as a right-hand side. The matrix and the RHS matrix
+/// are consumed.
+///
+/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any
+/// valid representation for `ArrayBase` (over `E`).
+impl<E, D1, D2> LeastSquaresSvdInto<D2, E, Ix2> for ArrayBase<D1, Ix2>
+where
+    E: Scalar + Lapack,
+    D1: DataMut<Elem = E>,
+    D2: DataMut<Elem = E>,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(rhs)`, where `rhs` is a
+    /// matrix. `A` and `rhs` are consumed.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares_into(
+        mut self,
+        mut rhs: ArrayBase<D2, Ix2>,
+    ) -> Result<LeastSquaresResult<E, Ix2>> {
+        self.least_squares_in_place(&mut rhs)
+    }
+}
+
+/// Solve least squares for mutable references and a vector
+/// as a right-hand side. Both values are overwritten in the
+/// call.
+///
+/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any
+/// valid representation for `ArrayBase` (over `E`).
+impl<E, D1, D2> LeastSquaresSvdInPlace<D2, E, Ix1> for ArrayBase<D1, Ix2>
+where
+    E: Scalar + Lapack,
+    D1: DataMut<Elem = E>,
+    D2: DataMut<Elem = E>,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(rhs)`, where `rhs` is a
+    /// vector. `A` and `rhs` are overwritten in the call.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares_in_place(
+        &mut self,
+        rhs: &mut ArrayBase<D2, Ix1>,
+    ) -> Result<LeastSquaresResult<E, Ix1>> {
+        if self.shape()[0] != rhs.shape()[0] {
+            return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape).into());
+        }
+        let (m, n) = (self.shape()[0], self.shape()[1]);
+        if n > m {
+            // we need a new rhs b/c it will be overwritten with the solution
+            // for which we need `n` entries
+            let mut new_rhs = Array1::<E>::zeros((n,));
+            new_rhs.slice_mut(s![0..m]).assign(rhs);
+            compute_least_squares_srhs(self, &mut new_rhs)
+        } else {
+            compute_least_squares_srhs(self, rhs)
+        }
+    }
+}
+
+fn compute_least_squares_srhs<E, D1, D2>(
+    a: &mut ArrayBase<D1, Ix2>,
+    rhs: &mut ArrayBase<D2, Ix1>,
+) -> Result<LeastSquaresResult<E, Ix1>>
+where
+    E: Scalar + Lapack,
+    D1: DataMut<Elem = E>,
+    D2: DataMut<Elem = E>,
+{
+    let LeastSquaresOutput::<E> {
+        singular_values,
+        rank,
+    } = E::least_squares(
+        a.layout()?,
+        a.as_allocated_mut()?,
+        rhs.as_slice_memory_order_mut()
+            .ok_or(LinalgError::MemoryNotCont)?,
+    )?;
+
+    let (m, n) = (a.shape()[0], a.shape()[1]);
+    let solution = rhs.slice(s![0..n]).to_owned();
+    let residual_sum_of_squares = compute_residual_scalar(m, n, rank, rhs);
+    Ok(LeastSquaresResult {
+        solution,
+        singular_values: Array::from_shape_vec((singular_values.len(),), singular_values)?,
+        rank,
+        residual_sum_of_squares,
+    })
+}
+
+fn compute_residual_scalar<E: Scalar, D: Data<Elem = E>>(
+    m: usize,
+    n: usize,
+    rank: i32,
+    b: &ArrayBase<D, Ix1>,
+) -> Option<Array<E::Real, Ix0>> {
+    if m < n || n != rank as usize {
+        return None;
+    }
+    let mut arr: Array<E::Real, Ix0> = Array::zeros(());
+    arr[()] = b.slice(s![n..]).mapv(|x| x.powi(2).abs()).sum();
+    Some(arr)
+}
+
+/// Solve least squares for mutable references and a matrix
+/// as a right-hand side. Both values are overwritten in the
+/// call.
+///
+/// `E` is one of `f32`, `f64`, `c32`, `c64`. `D1`, `D2` can be any
+/// valid representation for `ArrayBase` (over `E`).
+impl<E, D1, D2> LeastSquaresSvdInPlace<D2, E, Ix2> for ArrayBase<D1, Ix2>
+where
+    E: Scalar + Lapack + LeastSquaresSvdDivideConquer_,
+    D1: DataMut<Elem = E>,
+    D2: DataMut<Elem = E>,
+{
+    /// Solve a least squares problem of the form `Ax = rhs`
+    /// by calling `A.least_squares(rhs)`, where `rhs` is a
+    /// matrix. `A` and `rhs` are overwritten in the call.
+    ///
+    /// `A` and `rhs` must have the same layout, i.e. they must
+    /// be both either row- or column-major format, otherwise a
+    /// `IncompatibleShape` error is raised.
+    fn least_squares_in_place(
+        &mut self,
+        rhs: &mut ArrayBase<D2, Ix2>,
+    ) -> Result<LeastSquaresResult<E, Ix2>> {
+        if self.shape()[0] != rhs.shape()[0] {
+            return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape).into());
+        }
+        let (m, n) = (self.shape()[0], self.shape()[1]);
+        if n > m {
+            // we need a new rhs b/c it will be overwritten with the solution
+            // for which we need `n` entries
+            let k = rhs.shape()[1];
+            let mut new_rhs = match self.layout()? {
+                MatrixLayout::C { .. } => Array2::<E>::zeros((n, k)),
+                MatrixLayout::F { .. } => Array2::<E>::zeros((n, k).f()),
+            };
+            new_rhs.slice_mut(s![0..m, ..]).assign(rhs);
+            compute_least_squares_nrhs(self, &mut new_rhs)
+        } else {
+            compute_least_squares_nrhs(self, rhs)
+        }
+    }
+}
+
+fn compute_least_squares_nrhs<E, D1, D2>(
+    a: &mut ArrayBase<D1, Ix2>,
+    rhs: &mut ArrayBase<D2, Ix2>,
+) -> Result<LeastSquaresResult<E, Ix2>>
+where
+    E: Scalar + Lapack,
+    D1: DataMut<Elem = E>,
+    D2: DataMut<Elem = E>,
+{
+    let a_layout = a.layout()?;
+    let rhs_layout = rhs.layout()?;
+    let LeastSquaresOutput::<E> {
+        singular_values,
+        rank,
+    } = E::least_squares_nrhs(
+        a_layout,
+        a.as_allocated_mut()?,
+        rhs_layout,
+        rhs.as_allocated_mut()?,
+    )?;
+
+    let solution: Array2<E> = rhs.slice(s![..a.shape()[1], ..]).to_owned();
+    let singular_values = Array::from_shape_vec((singular_values.len(),), singular_values)?;
+    let (m, n) = (a.shape()[0], a.shape()[1]);
+    let residual_sum_of_squares = compute_residual_array1(m, n, rank, rhs);
+    Ok(LeastSquaresResult {
+        solution,
+        singular_values,
+        rank,
+        residual_sum_of_squares,
+    })
+}
+
+fn compute_residual_array1<E: Scalar, D: Data<Elem = E>>(
+    m: usize,
+    n: usize,
+    rank: i32,
+    b: &ArrayBase<D, Ix2>,
+) -> Option<Array1<E::Real>> {
+    if m < n || n != rank as usize {
+        return None;
+    }
+    Some(
+        b.slice(s![n.., ..])
+            .mapv(|x| x.powi(2).abs())
+            .sum_axis(Axis(0)),
+    )
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::{error::LinalgError, *};
+    use approx::AbsDiffEq;
+    use ndarray::*;
+
+    //
+    // Test that the different least squares traits work as intended on the
+    // different array types.
+    //
+    //               | least_squares | ls_into | ls_in_place |
+    // --------------+---------------+---------+-------------+
+    // Array         | yes           | yes     | yes         |
+    // ArcArray      | yes           | no      | no          |
+    // CowArray      | yes           | yes     | yes         |
+    // ArrayView     | yes           | no      | no          |
+    // ArrayViewMut  | yes           | no      | yes         |
+    //
+
+    fn assert_result<D1: Data<Elem = f64>, D2: Data<Elem = f64>>(
+        a: &ArrayBase<D1, Ix2>,
+        b: &ArrayBase<D2, Ix1>,
+        res: &LeastSquaresResult<f64, Ix1>,
+    ) {
+        assert_eq!(res.rank, 2);
+        let b_hat = a.dot(&res.solution);
+        let rssq = (b - &b_hat).mapv(|x| x.powi(2)).sum();
+        assert!(res.residual_sum_of_squares.as_ref().unwrap()[()].abs_diff_eq(&rssq, 1e-12));
+        assert!(res
+            .solution
+            .abs_diff_eq(&array![-0.428571428571429, 0.85714285714285], 1e-12));
+    }
+
+    #[test]
+    fn on_arc() {
+        let a: ArcArray2<f64> = array![[1., 2.], [4., 5.], [3., 4.]].into_shared();
+        let b: ArcArray1<f64> = array![1., 2., 3.].into_shared();
+        let res = a.least_squares(&b).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn on_cow() {
+        let a = CowArray::from(array![[1., 2.], [4., 5.], [3., 4.]]);
+        let b = CowArray::from(array![1., 2., 3.]);
+        let res = a.least_squares(&b).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn on_view() {
+        let a: Array2<f64> = array![[1., 2.], [4., 5.], [3., 4.]];
+        let b: Array1<f64> = array![1., 2., 3.];
+        let av = a.view();
+        let bv = b.view();
+        let res = av.least_squares(&bv).unwrap();
+        assert_result(&av, &bv, &res);
+    }
+
+    #[test]
+    fn on_view_mut() {
+        let mut a: Array2<f64> = array![[1., 2.], [4., 5.], [3., 4.]];
+        let mut b: Array1<f64> = array![1., 2., 3.];
+        let av = a.view_mut();
+        let bv = b.view_mut();
+        let res = av.least_squares(&bv).unwrap();
+        assert_result(&av, &bv, &res);
+    }
+
+    #[test]
+    fn on_cow_view() {
+        let a = CowArray::from(array![[1., 2.], [4., 5.], [3., 4.]]);
+        let b: Array1<f64> = array![1., 2., 3.];
+        let bv = b.view();
+        let res = a.least_squares(&bv).unwrap();
+        assert_result(&a, &bv, &res);
+    }
+
+    #[test]
+    fn into_on_owned() {
+        let a: Array2<f64> = array![[1., 2.], [4., 5.], [3., 4.]];
+        let b: Array1<f64> = array![1., 2., 3.];
+        let ac = a.clone();
+        let bc = b.clone();
+        let res = ac.least_squares_into(bc).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn into_on_arc() {
+        let a: ArcArray2<f64> = array![[1., 2.], [4., 5.], [3., 4.]].into_shared();
+        let b: ArcArray1<f64> = array![1., 2., 3.].into_shared();
+        let a2 = a.clone();
+        let b2 = b.clone();
+        let res = a2.least_squares_into(b2).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn into_on_cow() {
+        let a = CowArray::from(array![[1., 2.], [4., 5.], [3., 4.]]);
+        let b = CowArray::from(array![1., 2., 3.]);
+        let a2 = a.clone();
+        let b2 = b.clone();
+        let res = a2.least_squares_into(b2).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn into_on_owned_cow() {
+        let a: Array2<f64> = array![[1., 2.], [4., 5.], [3., 4.]];
+        let b = CowArray::from(array![1., 2., 3.]);
+        let ac = a.clone();
+        let b2 = b.clone();
+        let res = ac.least_squares_into(b2).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn in_place_on_owned() {
+        let a = array![[1., 2.], [4., 5.], [3., 4.]];
+        let b = array![1., 2., 3.];
+        let mut a2 = a.clone();
+        let mut b2 = b.clone();
+        let res = a2.least_squares_in_place(&mut b2).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn in_place_on_cow() {
+        let a = CowArray::from(array![[1., 2.], [4., 5.], [3., 4.]]);
+        let b = CowArray::from(array![1., 2., 3.]);
+        let mut a2 = a.clone();
+        let mut b2 = b.clone();
+        let res = a2.least_squares_in_place(&mut b2).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn in_place_on_mut_view() {
+        let a = array![[1., 2.], [4., 5.], [3., 4.]];
+        let b = array![1., 2., 3.];
+        let mut a2 = a.clone();
+        let mut b2 = b.clone();
+        let av = &mut a2.view_mut();
+        let bv = &mut b2.view_mut();
+        let res = av.least_squares_in_place(bv).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    #[test]
+    fn in_place_on_owned_cow() {
+        let a = array![[1., 2.], [4., 5.], [3., 4.]];
+        let b = CowArray::from(array![1., 2., 3.]);
+        let mut a2 = a.clone();
+        let mut b2 = b.clone();
+        let res = a2.least_squares_in_place(&mut b2).unwrap();
+        assert_result(&a, &b, &res);
+    }
+
+    //
+    // Testing error cases
+    //
+    #[test]
+    fn incompatible_shape_error_on_mismatching_num_rows() {
+        let a: Array2<f64> = array![[1., 2.], [4., 5.], [3., 4.]];
+        let b: Array1<f64> = array![1., 2.];
+        match a.least_squares(&b) {
+            Err(LinalgError::Shape(e)) if e.kind() == ErrorKind::IncompatibleShape => {}
+            _ => panic!("Should be raise IncompatibleShape"),
+        }
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/lib.rs.html b/src/ndarray_linalg/lib.rs.html new file mode 100644 index 00000000..5d8c00aa --- /dev/null +++ b/src/ndarray_linalg/lib.rs.html @@ -0,0 +1,224 @@ +lib.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+
//! The `ndarray-linalg` crate provides linear algebra functionalities for `ArrayBase`, the n-dimensional array data structure provided by [`ndarray`](https://github.com/rust-ndarray/ndarray).
+//!
+//! `ndarray-linalg` leverages [LAPACK](http://www.netlib.org/lapack/)'s routines using the bindings provided by [blas-lapack-rs/lapack](https://github.com/blas-lapack-rs/lapack).
+//!
+//! Linear algebra methods
+//! -----------------------
+//! - Decomposition methods:
+//!     - [QR decomposition](qr/index.html)
+//!     - [Cholesky/LU decomposition](cholesky/index.html)
+//!     - [Eigenvalue decomposition](eig/index.html)
+//!     - [Eigenvalue decomposition for Hermite matrices](eigh/index.html)
+//!     - [**S**ingular **V**alue **D**ecomposition](svd/index.html)
+//! - Solution of linear systems:
+//!    - [General matrices](solve/index.html)
+//!    - [Triangular matrices](triangular/index.html)
+//!    - [Hermitian/real symmetric matrices](solveh/index.html)
+//!    - [Tridiagonal matrices](tridiagonal/index.html)
+//! - [Inverse matrix computation](solve/trait.Inverse.html)
+//!
+//! Naming Convention
+//! -----------------------
+//! Each routine is usually exposed as a trait, implemented by the relevant types.
+//!
+//! For each routine there might be multiple "variants": different traits corresponding to the different ownership possibilities of the array you intend to work on.
+//!
+//! For example, if you are interested in the QR decomposition of a square matrix, you can use:
+//! - [QRSquare](qr/trait.QRSquare.html), if you hold an immutable reference (i.e. `&self`) to the matrix you want to decompose;
+//! - [QRSquareInplace](qr/trait.QRSquareInplace.html), if you hold a mutable reference (i.e. `&mut self`) to the matrix you want to decompose;
+//! - [QRSquareInto](qr/trait.QRSquareInto.html), if you can pass the matrix you want to decompose by value (e.g. `self`).
+//!
+//! Depending on the algorithm, each variant might require more or less copy operations of the underlying data.
+//!
+//! Details are provided in the description of each routine.
+//!
+//!  Utilities
+//!  -----------
+//!  - [Assertions for array](index.html#macros)
+//!  - [Random matrix generators](generate/index.html)
+//!  - [Scalar trait](types/trait.Scalar.html)
+
+#![allow(
+    clippy::module_inception,
+    clippy::many_single_char_names,
+    clippy::type_complexity,
+    clippy::ptr_arg
+)]
+
+#[macro_use]
+extern crate ndarray;
+
+pub mod assert;
+pub mod cholesky;
+pub mod convert;
+pub mod diagonal;
+pub mod eig;
+pub mod eigh;
+pub mod error;
+pub mod generate;
+pub mod inner;
+pub mod krylov;
+pub mod layout;
+pub mod least_squares;
+pub mod lobpcg;
+pub mod norm;
+pub mod operator;
+pub mod opnorm;
+pub mod qr;
+pub mod solve;
+pub mod solveh;
+pub mod svd;
+pub mod svddc;
+pub mod trace;
+pub mod triangular;
+pub mod tridiagonal;
+pub mod types;
+
+pub use crate::assert::*;
+pub use crate::cholesky::*;
+pub use crate::convert::*;
+pub use crate::diagonal::*;
+pub use crate::eig::*;
+pub use crate::eigh::*;
+pub use crate::generate::*;
+pub use crate::inner::*;
+pub use crate::layout::*;
+pub use crate::least_squares::*;
+pub use crate::lobpcg::{TruncatedEig, TruncatedOrder, TruncatedSvd};
+pub use crate::norm::*;
+pub use crate::operator::*;
+pub use crate::opnorm::*;
+pub use crate::qr::*;
+pub use crate::solve::*;
+pub use crate::solveh::*;
+pub use crate::svd::*;
+pub use crate::svddc::*;
+pub use crate::trace::*;
+pub use crate::triangular::*;
+pub use crate::tridiagonal::*;
+pub use crate::types::*;
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/lobpcg/eig.rs.html b/src/ndarray_linalg/lobpcg/eig.rs.html new file mode 100644 index 00000000..874537fe --- /dev/null +++ b/src/ndarray_linalg/lobpcg/eig.rs.html @@ -0,0 +1,418 @@ +eig.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+
use super::lobpcg::{lobpcg, LobpcgResult, Order};
+use crate::{generate, Scalar};
+use lax::Lapack;
+
+///! Implements truncated eigenvalue decomposition
+///
+use ndarray::prelude::*;
+use ndarray::stack;
+use ndarray::ScalarOperand;
+use num_traits::{Float, NumCast};
+
+/// Truncated eigenproblem solver
+///
+/// This struct wraps the LOBPCG algorithm and provides convenient builder-pattern access to
+/// parameter like maximal iteration, precision and constraint matrix. Furthermore it allows
+/// conversion into a iterative solver where each iteration step yields a new eigenvalue/vector
+/// pair.
+pub struct TruncatedEig<A: Scalar> {
+    order: Order,
+    problem: Array2<A>,
+    pub constraints: Option<Array2<A>>,
+    preconditioner: Option<Array2<A>>,
+    precision: f32,
+    maxiter: usize,
+}
+
+impl<A: Float + Scalar + ScalarOperand + Lapack + PartialOrd + Default> TruncatedEig<A> {
+    pub fn new(problem: Array2<A>, order: Order) -> TruncatedEig<A> {
+        TruncatedEig {
+            precision: 1e-5,
+            maxiter: problem.len_of(Axis(0)) * 2,
+            preconditioner: None,
+            constraints: None,
+            order,
+            problem,
+        }
+    }
+
+    pub fn precision(mut self, precision: f32) -> Self {
+        self.precision = precision;
+
+        self
+    }
+
+    pub fn maxiter(mut self, maxiter: usize) -> Self {
+        self.maxiter = maxiter;
+
+        self
+    }
+
+    pub fn orthogonal_to(mut self, constraints: Array2<A>) -> Self {
+        self.constraints = Some(constraints);
+
+        self
+    }
+
+    pub fn precondition_with(mut self, preconditioner: Array2<A>) -> Self {
+        self.preconditioner = Some(preconditioner);
+
+        self
+    }
+
+    // calculate the eigenvalues decompose
+    pub fn decompose(&self, num: usize) -> LobpcgResult<A> {
+        let x: Array2<f64> = generate::random((self.problem.len_of(Axis(0)), num));
+        let x = x.mapv(|x| NumCast::from(x).unwrap());
+
+        if let Some(ref preconditioner) = self.preconditioner {
+            lobpcg(
+                |y| self.problem.dot(&y),
+                x,
+                |mut y| y.assign(&preconditioner.dot(&y)),
+                self.constraints.clone(),
+                self.precision,
+                self.maxiter,
+                self.order.clone(),
+            )
+        } else {
+            lobpcg(
+                |y| self.problem.dot(&y),
+                x,
+                |_| {},
+                self.constraints.clone(),
+                self.precision,
+                self.maxiter,
+                self.order.clone(),
+            )
+        }
+    }
+}
+
+impl<A: Float + Scalar + ScalarOperand + Lapack + PartialOrd + Default> IntoIterator
+    for TruncatedEig<A>
+{
+    type Item = (Array1<A>, Array2<A>);
+    type IntoIter = TruncatedEigIterator<A>;
+
+    fn into_iter(self) -> TruncatedEigIterator<A> {
+        TruncatedEigIterator {
+            step_size: 1,
+            remaining: self.problem.len_of(Axis(0)),
+            eig: self,
+        }
+    }
+}
+
+/// Truncate eigenproblem iterator
+///
+/// This wraps a truncated eigenproblem and provides an iterator where each step yields a new
+/// eigenvalue/vector pair. Useful for generating pairs until a certain condition is met.
+pub struct TruncatedEigIterator<A: Scalar> {
+    step_size: usize,
+    remaining: usize,
+    eig: TruncatedEig<A>,
+}
+
+impl<A: Float + Scalar + ScalarOperand + Lapack + PartialOrd + Default> Iterator
+    for TruncatedEigIterator<A>
+{
+    type Item = (Array1<A>, Array2<A>);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.remaining == 0 {
+            return None;
+        }
+
+        let step_size = usize::min(self.step_size, self.remaining);
+        let res = self.eig.decompose(step_size);
+
+        match res {
+            LobpcgResult::Ok(vals, vecs, norms) | LobpcgResult::Err(vals, vecs, norms, _) => {
+                // abort if any eigenproblem did not converge
+                for r_norm in norms {
+                    if r_norm > NumCast::from(0.1).unwrap() {
+                        return None;
+                    }
+                }
+
+                // add the new eigenvector to the internal constrain matrix
+                let new_constraints = if let Some(ref constraints) = self.eig.constraints {
+                    let eigvecs_arr: Vec<_> = constraints
+                        .columns()
+                        .into_iter()
+                        .chain(vecs.columns().into_iter())
+                        .collect();
+
+                    stack(Axis(1), &eigvecs_arr).unwrap()
+                } else {
+                    vecs.clone()
+                };
+
+                self.eig.constraints = Some(new_constraints);
+                self.remaining -= step_size;
+
+                Some((vals, vecs))
+            }
+            LobpcgResult::NoResult(_) => None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Order;
+    use super::TruncatedEig;
+    use ndarray::{arr1, Array2};
+
+    #[test]
+    fn test_truncated_eig() {
+        let diag = arr1(&[
+            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19.,
+            20.,
+        ]);
+        let a = Array2::from_diag(&diag);
+
+        let teig = TruncatedEig::new(a, Order::Largest)
+            .precision(1e-5)
+            .maxiter(500);
+
+        let res = teig
+            .into_iter()
+            .take(3)
+            .flat_map(|x| x.0.to_vec())
+            .collect::<Vec<_>>();
+        let ground_truth = vec![20., 19., 18.];
+
+        assert!(
+            ground_truth
+                .into_iter()
+                .zip(res.into_iter())
+                .map(|(x, y)| (x - y) * (x - y))
+                .sum::<f64>()
+                < 0.01
+        );
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/lobpcg/lobpcg.rs.html b/src/ndarray_linalg/lobpcg/lobpcg.rs.html new file mode 100644 index 00000000..0b8adf0a --- /dev/null +++ b/src/ndarray_linalg/lobpcg/lobpcg.rs.html @@ -0,0 +1,1248 @@ +lobpcg.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+
///! Locally Optimal Block Preconditioned Conjugated
+///!
+///! This module implements the Locally Optimal Block Preconditioned Conjugated (LOBPCG) algorithm,
+///which can be used as a solver for large symmetric positive definite eigenproblems.
+use crate::error::{LinalgError, Result};
+use crate::{cholesky::*, close_l2, eigh::*, norm::*, triangular::*};
+use cauchy::Scalar;
+use lax::Lapack;
+use ndarray::prelude::*;
+use ndarray::{Data, OwnedRepr, ScalarOperand};
+use num_traits::{Float, NumCast};
+
+/// Find largest or smallest eigenvalues
+#[derive(Debug, Clone)]
+pub enum Order {
+    Largest,
+    Smallest,
+}
+
+/// The result of the eigensolver
+///
+/// In the best case the eigensolver has converged with a result better than the given threshold,
+/// then a `LobpcgResult::Ok` gives the eigenvalues, eigenvectors and norms. If an error ocurred
+/// during the process, it is returned in `LobpcgResult::Err`, but the best result is still returned,
+/// as it could be usable. If there is no result at all, then `LobpcgResult::NoResult` is returned.
+/// This happens if the algorithm fails in an early stage, for example if the matrix `A` is not SPD
+#[derive(Debug)]
+pub enum LobpcgResult<A> {
+    Ok(Array1<A>, Array2<A>, Vec<A>),
+    Err(Array1<A>, Array2<A>, Vec<A>, LinalgError),
+    NoResult(LinalgError),
+}
+
+/// Solve full eigenvalue problem, sort by `order` and truncate to `size`
+fn sorted_eig<S: Data<Elem = A>, A: Scalar + Lapack>(
+    a: ArrayBase<S, Ix2>,
+    b: Option<ArrayBase<S, Ix2>>,
+    size: usize,
+    order: &Order,
+) -> Result<(Array1<A>, Array2<A>)> {
+    let n = a.len_of(Axis(0));
+
+    let (vals, vecs) = match b {
+        Some(b) => (a, b).eigh(UPLO::Upper).map(|x| (x.0, (x.1).0))?,
+        _ => a.eigh(UPLO::Upper)?,
+    };
+
+    Ok(match order {
+        Order::Largest => (
+            vals.slice_move(s![n-size..; -1]).mapv(Scalar::from_real),
+            vecs.slice_move(s![.., n-size..; -1]),
+        ),
+        Order::Smallest => (
+            vals.slice_move(s![..size]).mapv(Scalar::from_real),
+            vecs.slice_move(s![.., ..size]),
+        ),
+    })
+}
+
+/// Masks a matrix with the given `matrix`
+fn ndarray_mask<A: Scalar>(matrix: ArrayView2<A>, mask: &[bool]) -> Array2<A> {
+    assert_eq!(mask.len(), matrix.ncols());
+
+    let indices = (0..mask.len())
+        .zip(mask.iter())
+        .filter(|(_, b)| **b)
+        .map(|(a, _)| a)
+        .collect::<Vec<usize>>();
+
+    matrix.select(Axis(1), &indices)
+}
+
+/// Applies constraints ensuring that a matrix is orthogonal to it
+///
+/// This functions takes a matrix `v` and constraint-matrix `y` and orthogonalize `v` to `y`.
+fn apply_constraints<A: Scalar + Lapack>(
+    mut v: ArrayViewMut<A, Ix2>,
+    cholesky_yy: &CholeskyFactorized<OwnedRepr<A>>,
+    y: ArrayView2<A>,
+) {
+    let gram_yv = y.t().dot(&v);
+
+    let u = gram_yv
+        .columns()
+        .into_iter()
+        .flat_map(|x| {
+            let res = cholesky_yy.solvec(&x).unwrap();
+
+            res.to_vec()
+        })
+        .collect::<Vec<A>>();
+
+    let rows = gram_yv.len_of(Axis(0));
+    let u = Array2::from_shape_vec((rows, u.len() / rows), u).unwrap();
+
+    v -= &(y.dot(&u));
+}
+
+/// Orthonormalize `V` with Cholesky factorization
+///
+/// This also returns the matrix `R` of the `QR` problem
+fn orthonormalize<T: Scalar + Lapack>(v: Array2<T>) -> Result<(Array2<T>, Array2<T>)> {
+    let gram_vv = v.t().dot(&v);
+    let gram_vv_fac = gram_vv.cholesky(UPLO::Lower)?;
+
+    close_l2(
+        &gram_vv,
+        &gram_vv_fac.dot(&gram_vv_fac.t()),
+        NumCast::from(1e-5).unwrap(),
+    );
+
+    let v_t = v.reversed_axes();
+    let u = gram_vv_fac
+        .solve_triangular(UPLO::Lower, Diag::NonUnit, &v_t)?
+        .reversed_axes();
+
+    Ok((u, gram_vv_fac))
+}
+
+/// Eigenvalue solver for large symmetric positive definite (SPD) eigenproblems
+///
+/// # Arguments
+/// * `a` - An operator defining the problem, usually a sparse (sometimes also dense) matrix
+/// multiplication. Also called the "stiffness matrix".
+/// * `x` - Initial approximation of the k eigenvectors. If `a` has shape=(n,n), then `x` should
+/// have shape=(n,k).
+/// * `m` - Preconditioner to `a`, by default the identity matrix. Should approximate the inverse
+/// of `a`.
+/// * `y` - Constraints of (n,size_y), iterations are performed in the orthogonal complement of the
+/// column-space of `y`. It must be full rank.
+/// * `tol` - The tolerance values defines at which point the solver stops the optimization. The approximation
+/// of a eigenvalue stops when then l2-norm of the residual is below this threshold.
+/// * `maxiter` - The maximal number of iterations
+/// * `order` - Whether to solve for the largest or lowest eigenvalues
+///
+/// The function returns an `LobpcgResult` with the eigenvalue/eigenvector and achieved residual norm
+/// for it. All iterations are tracked and the optimal solution returned. In case of an error a
+/// special variant `LobpcgResult::NotConverged` additionally carries the error. This can happen when
+/// the precision of the matrix is too low (switch then from `f32` to `f64` for example).
+pub fn lobpcg<
+    A: Float + Scalar + Lapack + ScalarOperand + PartialOrd + Default,
+    F: Fn(ArrayView2<A>) -> Array2<A>,
+    G: Fn(ArrayViewMut2<A>),
+>(
+    a: F,
+    mut x: Array2<A>,
+    m: G,
+    y: Option<Array2<A>>,
+    tol: f32,
+    maxiter: usize,
+    order: Order,
+) -> LobpcgResult<A> {
+    // the initital approximation should be maximal square
+    // n is the dimensionality of the problem
+    let (n, size_x) = (x.nrows(), x.ncols());
+    assert!(size_x <= n);
+
+    /*let size_y = match y {
+        Some(ref y) => y.ncols(),
+        _ => 0,
+    };
+
+    if (n - size_y) < 5 * size_x {
+        panic!("Please use a different approach, the LOBPCG method only supports the calculation of a couple of eigenvectors!");
+    }*/
+
+    // cap the number of iteration
+    let mut iter = usize::min(n * 10, maxiter);
+    let tol = NumCast::from(tol).unwrap();
+
+    // calculate cholesky factorization of YY' and apply constraints to initial guess
+    let cholesky_yy = y.as_ref().map(|y| {
+        let cholesky_yy = y.t().dot(y).factorizec(UPLO::Lower).unwrap();
+        apply_constraints(x.view_mut(), &cholesky_yy, y.view());
+        cholesky_yy
+    });
+
+    // orthonormalize the initial guess
+    let (x, _) = match orthonormalize(x) {
+        Ok(x) => x,
+        Err(err) => return LobpcgResult::NoResult(err),
+    };
+
+    // calculate AX and XAX for Rayleigh quotient
+    let ax = a(x.view());
+    let xax = x.t().dot(&ax);
+
+    // perform eigenvalue decomposition of XAX
+    let (mut lambda, eig_block) = match sorted_eig(xax.view(), None, size_x, &order) {
+        Ok(x) => x,
+        Err(err) => return LobpcgResult::NoResult(err),
+    };
+
+    // initiate approximation of the eigenvector
+    let mut x = x.dot(&eig_block);
+    let mut ax = ax.dot(&eig_block);
+
+    // track residual below threshold
+    let mut activemask = vec![true; size_x];
+
+    // track residuals and best result
+    let mut residual_norms_history = Vec::new();
+    let mut best_result = None;
+
+    let mut previous_block_size = size_x;
+
+    let mut ident: Array2<A> = Array2::eye(size_x);
+    let ident0: Array2<A> = Array2::eye(size_x);
+    let two: A = NumCast::from(2.0).unwrap();
+
+    let mut previous_p_ap: Option<(Array2<A>, Array2<A>)> = None;
+    let mut explicit_gram_flag = true;
+
+    let final_norm = loop {
+        // calculate residual
+        let lambda_diag = Array2::from_diag(&lambda);
+        let lambda_x = x.dot(&lambda_diag);
+
+        // calculate residual AX - lambdaX
+        let r = &ax - &lambda_x;
+
+        // calculate L2 norm of error for every eigenvalue
+        let residual_norms = r
+            .columns()
+            .into_iter()
+            .map(|x| x.norm())
+            .collect::<Vec<A::Real>>();
+        residual_norms_history.push(residual_norms.clone());
+
+        // compare best result and update if we improved
+        let sum_rnorm: A::Real = residual_norms.iter().cloned().sum();
+        if best_result
+            .as_ref()
+            .map(|x: &(_, _, Vec<A::Real>)| x.2.iter().cloned().sum::<A::Real>() > sum_rnorm)
+            .unwrap_or(true)
+        {
+            best_result = Some((lambda.clone(), x.clone(), residual_norms.clone()));
+        }
+
+        // disable eigenvalues which are below the tolerance threshold
+        activemask = residual_norms
+            .iter()
+            .zip(activemask.iter())
+            .map(|(x, a)| *x > tol && *a)
+            .collect();
+
+        // resize identity block if necessary
+        let current_block_size = activemask.iter().filter(|x| **x).count();
+        if current_block_size != previous_block_size {
+            previous_block_size = current_block_size;
+            ident = Array2::eye(current_block_size);
+        }
+
+        // if we are below the threshold for all eigenvalue or exceeded the number of iteration,
+        // abort
+        if current_block_size == 0 || iter == 0 {
+            break Ok(residual_norms);
+        }
+
+        // select active eigenvalues, apply pre-conditioner, orthogonalize to Y and orthonormalize
+        let mut active_block_r = ndarray_mask(r.view(), &activemask);
+        // apply preconditioner
+        m(active_block_r.view_mut());
+        // apply constraints to the preconditioned residuals
+        if let (Some(ref y), Some(ref cholesky_yy)) = (&y, &cholesky_yy) {
+            apply_constraints(active_block_r.view_mut(), cholesky_yy, y.view());
+        }
+        // orthogonalize the preconditioned residual to x
+        active_block_r -= &x.dot(&x.t().dot(&active_block_r));
+
+        let (r, _) = match orthonormalize(active_block_r) {
+            Ok(x) => x,
+            Err(err) => break Err(err),
+        };
+
+        let ar = a(r.view());
+
+        // check whether `A` is of type `f32` or `f64`
+        let max_rnorm_float = if A::epsilon() > NumCast::from(1e-8).unwrap() {
+            NumCast::from(1.0).unwrap()
+        } else {
+            NumCast::from(1.0e-8).unwrap()
+        };
+
+        // if we are once below the max_rnorm, enable explicit gram flag
+        let max_norm = residual_norms
+            .into_iter()
+            .fold(A::Real::neg_infinity(), A::Real::max);
+        explicit_gram_flag = max_norm <= max_rnorm_float || explicit_gram_flag;
+
+        // perform the Rayleigh Ritz procedure
+        let xar = x.t().dot(&ar);
+        let mut rar = r.t().dot(&ar);
+
+        // for small residuals calculate covariance matrices explicitely, otherwise approximate
+        // them such that X is orthogonal and uncorrelated to the residual R and use eigenvalues of
+        // previous decomposition
+        let (xax, xx, rr, xr) = if explicit_gram_flag {
+            rar = (&rar + &rar.t()) / two;
+            let xax = x.t().dot(&ax);
+
+            (
+                (&xax + &xax.t()) / two,
+                x.t().dot(&x),
+                r.t().dot(&r),
+                x.t().dot(&r),
+            )
+        } else {
+            (
+                lambda_diag,
+                ident0.clone(),
+                ident.clone(),
+                Array2::zeros((size_x, current_block_size)),
+            )
+        };
+
+        // mask and orthonormalize P and AP
+        let mut p_ap = previous_p_ap
+            .as_ref()
+            .and_then(|(p, ap)| {
+                let active_p = ndarray_mask(p.view(), &activemask);
+                let active_ap = ndarray_mask(ap.view(), &activemask);
+
+                orthonormalize(active_p).map(|x| (active_ap, x)).ok()
+            })
+            .and_then(|(active_ap, (active_p, p_r))| {
+                // orthonormalize AP with R^{-1} of A
+                let active_ap = active_ap.reversed_axes();
+                p_r.solve_triangular(UPLO::Lower, Diag::NonUnit, &active_ap)
+                    .map(|active_ap| (active_p, active_ap.reversed_axes()))
+                    .ok()
+            });
+
+        // compute symmetric gram matrices and calculate solution of eigenproblem
+        //
+        // first try to compute the eigenvalue decomposition of the span{R, X, P},
+        // if this fails (or the algorithm was restarted), then just use span{R, X}
+        let result = p_ap
+            .as_ref()
+            .ok_or(LinalgError::Lapack(
+                lax::error::Error::LapackComputationalFailure { return_code: 1 },
+            ))
+            .and_then(|(active_p, active_ap)| {
+                let xap = x.t().dot(active_ap);
+                let rap = r.t().dot(active_ap);
+                let pap = active_p.t().dot(active_ap);
+                let xp = x.t().dot(active_p);
+                let rp = r.t().dot(active_p);
+                let (pap, pp) = if explicit_gram_flag {
+                    ((&pap + &pap.t()) / two, active_p.t().dot(active_p))
+                } else {
+                    (pap, ident.clone())
+                };
+
+                sorted_eig(
+                    concatenate![
+                        Axis(0),
+                        concatenate![Axis(1), xax, xar, xap],
+                        concatenate![Axis(1), xar.t(), rar, rap],
+                        concatenate![Axis(1), xap.t(), rap.t(), pap]
+                    ],
+                    Some(concatenate![
+                        Axis(0),
+                        concatenate![Axis(1), xx, xr, xp],
+                        concatenate![Axis(1), xr.t(), rr, rp],
+                        concatenate![Axis(1), xp.t(), rp.t(), pp]
+                    ]),
+                    size_x,
+                    &order,
+                )
+            })
+            .or_else(|_| {
+                p_ap = None;
+
+                sorted_eig(
+                    concatenate![
+                        Axis(0),
+                        concatenate![Axis(1), xax, xar],
+                        concatenate![Axis(1), xar.t(), rar]
+                    ],
+                    Some(concatenate![
+                        Axis(0),
+                        concatenate![Axis(1), xx, xr],
+                        concatenate![Axis(1), xr.t(), rr]
+                    ]),
+                    size_x,
+                    &order,
+                )
+            });
+
+        // update eigenvalues and eigenvectors (lambda is also used in the next iteration)
+        let eig_vecs;
+        match result {
+            Ok((x, y)) => {
+                lambda = x;
+                eig_vecs = y;
+            }
+            Err(x) => break Err(x),
+        }
+
+        // approximate eigenvector X and conjugate vectors P with solution of eigenproblem
+        let (p, ap, tau) = if let Some((active_p, active_ap)) = p_ap {
+            // tau are eigenvalues to basis of X
+            let tau = eig_vecs.slice(s![..size_x, ..]);
+            // alpha are eigenvalues to basis of R
+            let alpha = eig_vecs.slice(s![size_x..size_x + current_block_size, ..]);
+            // gamma are eigenvalues to basis of P
+            let gamma = eig_vecs.slice(s![size_x + current_block_size.., ..]);
+
+            // update AP and P in span{R, P} as linear combination
+            let updated_p = r.dot(&alpha) + active_p.dot(&gamma);
+            let updated_ap = ar.dot(&alpha) + active_ap.dot(&gamma);
+
+            (updated_p, updated_ap, tau)
+        } else {
+            // tau are eigenvalues to basis of X
+            let tau = eig_vecs.slice(s![..size_x, ..]);
+            // alpha are eigenvalues to basis of R
+            let alpha = eig_vecs.slice(s![size_x.., ..]);
+
+            // update AP and P as linear combination of the residual matrix R
+            let updated_p = r.dot(&alpha);
+            let updated_ap = ar.dot(&alpha);
+
+            (updated_p, updated_ap, tau)
+        };
+
+        // update approximation of X as linear combinations of span{X, P, R}
+        x = x.dot(&tau) + &p;
+        ax = ax.dot(&tau) + &ap;
+
+        previous_p_ap = Some((p, ap));
+
+        iter -= 1;
+    };
+
+    // retrieve best result and convert norm into `A`
+    let (vals, vecs, rnorm) = best_result.unwrap();
+    let rnorm = rnorm.into_iter().map(Scalar::from_real).collect();
+
+    match final_norm {
+        Ok(_) => LobpcgResult::Ok(vals, vecs, rnorm),
+        Err(err) => LobpcgResult::Err(vals, vecs, rnorm, err),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::lobpcg;
+    use super::ndarray_mask;
+    use super::orthonormalize;
+    use super::sorted_eig;
+    use super::LobpcgResult;
+    use super::Order;
+    use crate::close_l2;
+    use crate::generate;
+    use crate::qr::*;
+    use ndarray::prelude::*;
+
+    /// Test the `sorted_eigen` function
+    #[test]
+    fn test_sorted_eigen() {
+        let matrix: Array2<f64> = generate::random((10, 10)) * 10.0;
+        let matrix = matrix.t().dot(&matrix);
+
+        // return all eigenvectors with largest first
+        let (vals, vecs) = sorted_eig(matrix.view(), None, 10, &Order::Largest).unwrap();
+
+        // calculate V * A * V' and compare to original matrix
+        let diag = Array2::from_diag(&vals);
+        let rec = (vecs.dot(&diag)).dot(&vecs.t());
+
+        close_l2(&matrix, &rec, 1e-5);
+    }
+
+    /// Test the masking function
+    #[test]
+    fn test_masking() {
+        let matrix: Array2<f64> = generate::random((10, 5)) * 10.0;
+        let masked_matrix = ndarray_mask(matrix.view(), &[true, true, false, true, false]);
+        close_l2(
+            &masked_matrix.slice(s![.., 2]),
+            &matrix.slice(s![.., 3]),
+            1e-12,
+        );
+    }
+
+    /// Test orthonormalization of a random matrix
+    #[test]
+    fn test_orthonormalize() {
+        let matrix: Array2<f64> = generate::random((10, 10)) * 10.0;
+
+        let (n, l) = orthonormalize(matrix.clone()).unwrap();
+
+        // check for orthogonality
+        let identity = n.dot(&n.t());
+        close_l2(&identity, &Array2::eye(10), 1e-2);
+
+        // compare returned factorization with QR decomposition
+        let (_, r) = matrix.qr().unwrap();
+        close_l2(&r.mapv(|x| x.abs()), &l.t().mapv(|x| x.abs()), 1e-2);
+    }
+
+    fn assert_symmetric(a: &Array2<f64>) {
+        close_l2(a, &a.t(), 1e-5);
+    }
+
+    fn check_eigenvalues(a: &Array2<f64>, order: Order, num: usize, ground_truth_eigvals: &[f64]) {
+        assert_symmetric(a);
+
+        let n = a.len_of(Axis(0));
+        let x: Array2<f64> = generate::random((n, num));
+
+        let result = lobpcg(|y| a.dot(&y), x, |_| {}, None, 1e-5, n * 2, order);
+        match result {
+            LobpcgResult::Ok(vals, _, r_norms) | LobpcgResult::Err(vals, _, r_norms, _) => {
+                // check convergence
+                for (i, norm) in r_norms.into_iter().enumerate() {
+                    if norm > 1e-5 {
+                        println!("==== Assertion Failed ====");
+                        println!("The {}th eigenvalue estimation did not converge!", i);
+                        panic!("Too large deviation of residual norm: {} > 0.01", norm);
+                    }
+                }
+
+                // check correct order of eigenvalues
+                if ground_truth_eigvals.len() == num {
+                    close_l2(
+                        &Array1::from(ground_truth_eigvals.to_vec()),
+                        &vals,
+                        num as f64 * 5e-4,
+                    )
+                }
+            }
+            LobpcgResult::NoResult(err) => panic!("Did not converge: {:?}", err),
+        }
+    }
+
+    /// Test the eigensolver with a identity matrix problem and a random initial solution
+    #[test]
+    fn test_eigsolver_diag() {
+        let diag = arr1(&[
+            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19.,
+            20.,
+        ]);
+        let a = Array2::from_diag(&diag);
+
+        check_eigenvalues(&a, Order::Largest, 3, &[20., 19., 18.]);
+        check_eigenvalues(&a, Order::Smallest, 3, &[1., 2., 3.]);
+    }
+
+    /// Test the eigensolver with matrix of constructed eigenvalues
+    #[test]
+    fn test_eigsolver_constructed() {
+        let n = 50;
+        let tmp = generate::random((n, n));
+        //let (v, _) = tmp.qr_square().unwrap();
+        let (v, _) = orthonormalize(tmp).unwrap();
+
+        // set eigenvalues in decreasing order
+        let t = Array2::from_diag(&Array1::linspace(n as f64, -(n as f64), n));
+        let a = v.dot(&t.dot(&v.t()));
+
+        // find five largest eigenvalues
+        check_eigenvalues(&a, Order::Largest, 5, &[50.0, 48.0, 46.0, 44.0, 42.0]);
+        check_eigenvalues(&a, Order::Smallest, 5, &[-50.0, -48.0, -46.0, -44.0, -42.0]);
+    }
+
+    #[test]
+    fn test_eigsolver_constrained() {
+        let diag = arr1(&[1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]);
+        let a = Array2::from_diag(&diag);
+        let x: Array2<f64> = generate::random((10, 1));
+        let y: Array2<f64> = arr2(&[
+            [1.0, 0., 0., 0., 0., 0., 0., 0., 0., 0.],
+            [0., 1.0, 0., 0., 0., 0., 0., 0., 0., 0.],
+        ])
+        .reversed_axes();
+
+        let result = lobpcg(
+            |y| a.dot(&y),
+            x,
+            |_| {},
+            Some(y),
+            1e-10,
+            50,
+            Order::Smallest,
+        );
+        match result {
+            LobpcgResult::Ok(vals, vecs, r_norms) | LobpcgResult::Err(vals, vecs, r_norms, _) => {
+                // check convergence
+                for (i, norm) in r_norms.into_iter().enumerate() {
+                    if norm > 0.01 {
+                        println!("==== Assertion Failed ====");
+                        println!("The {}th eigenvalue estimation did not converge!", i);
+                        panic!("Too large deviation of residual norm: {} > 0.01", norm);
+                    }
+                }
+
+                // should be the third eigenvalue
+                close_l2(&vals, &Array1::from(vec![3.0]), 1e-10);
+                close_l2(
+                    &vecs.column(0).mapv(|x| x.abs()),
+                    &arr1(&[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]),
+                    1e-5,
+                );
+            }
+            LobpcgResult::NoResult(err) => panic!("Did not converge: {:?}", err),
+        }
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/lobpcg/mod.rs.html b/src/ndarray_linalg/lobpcg/mod.rs.html new file mode 100644 index 00000000..d6da1343 --- /dev/null +++ b/src/ndarray_linalg/lobpcg/mod.rs.html @@ -0,0 +1,40 @@ +mod.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+
mod eig;
+mod lobpcg;
+mod svd;
+
+pub use eig::TruncatedEig;
+pub use lobpcg::{lobpcg, LobpcgResult, Order as TruncatedOrder};
+pub use svd::TruncatedSvd;
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/lobpcg/svd.rs.html b/src/ndarray_linalg/lobpcg/svd.rs.html new file mode 100644 index 00000000..30e900e5 --- /dev/null +++ b/src/ndarray_linalg/lobpcg/svd.rs.html @@ -0,0 +1,486 @@ +svd.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+
///! Truncated singular value decomposition
+///!
+///! This module computes the k largest/smallest singular values/vectors for a dense matrix.
+use super::lobpcg::{lobpcg, LobpcgResult, Order};
+use crate::error::Result;
+use crate::generate;
+use cauchy::Scalar;
+use lax::Lapack;
+use ndarray::prelude::*;
+use ndarray::ScalarOperand;
+use num_traits::{Float, NumCast};
+use std::ops::DivAssign;
+
+/// The result of a eigenvalue decomposition, not yet transformed into singular values/vectors
+///
+/// Provides methods for either calculating just the singular values with reduced cost or the
+/// vectors with additional cost of matrix multiplication.
+#[derive(Debug)]
+pub struct TruncatedSvdResult<A> {
+    eigvals: Array1<A>,
+    eigvecs: Array2<A>,
+    problem: Array2<A>,
+    ngm: bool,
+}
+
+impl<A: Float + PartialOrd + DivAssign<A> + 'static + MagnitudeCorrection> TruncatedSvdResult<A> {
+    /// Returns singular values ordered by magnitude with indices.
+    fn singular_values_with_indices(&self) -> (Array1<A>, Vec<usize>) {
+        // numerate eigenvalues
+        let mut a = self.eigvals.iter().enumerate().collect::<Vec<_>>();
+
+        // sort by magnitude
+        a.sort_by(|(_, x), (_, y)| x.partial_cmp(y).unwrap().reverse());
+
+        // calculate cut-off magnitude (borrowed from scipy)
+        let cutoff = A::epsilon() * // float precision
+                     A::correction() * // correction term (see trait below)
+                     *a[0].1; // max eigenvalue
+
+        // filter low singular values away
+        let (values, indices): (Vec<A>, Vec<usize>) = a
+            .into_iter()
+            .filter(|(_, x)| *x > &cutoff)
+            .map(|(a, b)| (b.sqrt(), a))
+            .unzip();
+
+        (Array1::from(values), indices)
+    }
+
+    /// Returns singular values ordered by magnitude
+    pub fn values(&self) -> Array1<A> {
+        let (values, _) = self.singular_values_with_indices();
+
+        values
+    }
+
+    /// Returns singular values, left-singular vectors and right-singular vectors
+    pub fn values_vectors(&self) -> (Array2<A>, Array1<A>, Array2<A>) {
+        let (values, indices) = self.singular_values_with_indices();
+
+        // branch n > m (for A is [n x m])
+        let (u, v) = if self.ngm {
+            let vlarge = self.eigvecs.select(Axis(1), &indices);
+            let mut ularge = self.problem.dot(&vlarge);
+
+            ularge
+                .columns_mut()
+                .into_iter()
+                .zip(values.iter())
+                .for_each(|(mut a, b)| a.mapv_inplace(|x| x / *b));
+
+            (ularge, vlarge)
+        } else {
+            let ularge = self.eigvecs.select(Axis(1), &indices);
+
+            let mut vlarge = self.problem.t().dot(&ularge);
+            vlarge
+                .columns_mut()
+                .into_iter()
+                .zip(values.iter())
+                .for_each(|(mut a, b)| a.mapv_inplace(|x| x / *b));
+
+            (ularge, vlarge)
+        };
+
+        (u, values, v.reversed_axes())
+    }
+}
+
+/// Truncated singular value decomposition
+///
+/// Wraps the LOBPCG algorithm and provides convenient builder-pattern access to
+/// parameter like maximal iteration, precision and constraint matrix.
+pub struct TruncatedSvd<A: Scalar> {
+    order: Order,
+    problem: Array2<A>,
+    precision: f32,
+    maxiter: usize,
+}
+
+impl<A: Float + Scalar + ScalarOperand + Lapack + PartialOrd + Default> TruncatedSvd<A> {
+    pub fn new(problem: Array2<A>, order: Order) -> TruncatedSvd<A> {
+        TruncatedSvd {
+            precision: 1e-5,
+            maxiter: problem.len_of(Axis(0)) * 2,
+            order,
+            problem,
+        }
+    }
+
+    pub fn precision(mut self, precision: f32) -> Self {
+        self.precision = precision;
+
+        self
+    }
+
+    pub fn maxiter(mut self, maxiter: usize) -> Self {
+        self.maxiter = maxiter;
+
+        self
+    }
+
+    // calculate the eigenvalue decomposition
+    pub fn decompose(self, num: usize) -> Result<TruncatedSvdResult<A>> {
+        if num < 1 {
+            panic!("The number of singular values to compute should be larger than zero!");
+        }
+
+        let (n, m) = (self.problem.nrows(), self.problem.ncols());
+
+        // generate initial matrix
+        let x: Array2<f32> = generate::random((usize::min(n, m), num));
+        let x = x.mapv(|x| NumCast::from(x).unwrap());
+
+        // square precision because the SVD squares the eigenvalue as well
+        let precision = self.precision * self.precision;
+
+        // use problem definition with less operations required
+        let res = if n > m {
+            lobpcg(
+                |y| self.problem.t().dot(&self.problem.dot(&y)),
+                x,
+                |_| {},
+                None,
+                precision,
+                self.maxiter,
+                self.order.clone(),
+            )
+        } else {
+            lobpcg(
+                |y| self.problem.dot(&self.problem.t().dot(&y)),
+                x,
+                |_| {},
+                None,
+                precision,
+                self.maxiter,
+                self.order.clone(),
+            )
+        };
+
+        // convert into TruncatedSvdResult
+        match res {
+            LobpcgResult::Ok(vals, vecs, _) | LobpcgResult::Err(vals, vecs, _, _) => {
+                Ok(TruncatedSvdResult {
+                    problem: self.problem,
+                    eigvals: vals,
+                    eigvecs: vecs,
+                    ngm: n > m,
+                })
+            }
+            LobpcgResult::NoResult(err) => Err(err),
+        }
+    }
+}
+
+pub trait MagnitudeCorrection {
+    fn correction() -> Self;
+}
+
+impl MagnitudeCorrection for f32 {
+    fn correction() -> Self {
+        1.0e3
+    }
+}
+
+impl MagnitudeCorrection for f64 {
+    fn correction() -> Self {
+        1.0e6
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Order;
+    use super::TruncatedSvd;
+    use crate::{close_l2, generate};
+
+    use ndarray::{arr1, arr2, Array2};
+
+    #[test]
+    fn test_truncated_svd() {
+        let a = arr2(&[[3., 2., 2.], [2., 3., -2.]]);
+
+        let res = TruncatedSvd::new(a, Order::Largest)
+            .precision(1e-5)
+            .maxiter(10)
+            .decompose(2)
+            .unwrap();
+
+        let (_, sigma, _) = res.values_vectors();
+
+        close_l2(&sigma, &arr1(&[5.0, 3.0]), 1e-5);
+    }
+
+    #[test]
+    fn test_truncated_svd_random() {
+        let a: Array2<f64> = generate::random((50, 10));
+
+        let res = TruncatedSvd::new(a.clone(), Order::Largest)
+            .precision(1e-5)
+            .maxiter(10)
+            .decompose(10)
+            .unwrap();
+
+        let (u, sigma, v_t) = res.values_vectors();
+        let reconstructed = u.dot(&Array2::from_diag(&sigma).dot(&v_t));
+
+        close_l2(&a, &reconstructed, 1e-5);
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/norm.rs.html b/src/ndarray_linalg/norm.rs.html new file mode 100644 index 00000000..3fb7bf73 --- /dev/null +++ b/src/ndarray_linalg/norm.rs.html @@ -0,0 +1,168 @@ +norm.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+
//! Norm of vectors
+
+use ndarray::*;
+use num_traits::Zero;
+
+use super::types::*;
+
+/// Define norm as a metric linear space (not as a matrix)
+///
+/// For operator norms, see opnorm module
+pub trait Norm {
+    type Output;
+    /// rename of `norm_l2`
+    fn norm(&self) -> Self::Output {
+        self.norm_l2()
+    }
+    /// L-1 norm
+    fn norm_l1(&self) -> Self::Output;
+    /// L-2 norm
+    fn norm_l2(&self) -> Self::Output;
+    /// maximum norm
+    fn norm_max(&self) -> Self::Output;
+}
+
+impl<A, S, D> Norm for ArrayBase<S, D>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+    D: Dimension,
+{
+    type Output = A::Real;
+    fn norm_l1(&self) -> Self::Output {
+        self.iter().map(|x| x.abs()).sum()
+    }
+    fn norm_l2(&self) -> Self::Output {
+        self.iter().map(|x| x.square()).sum::<A::Real>().sqrt()
+    }
+    fn norm_max(&self) -> Self::Output {
+        self.iter().fold(A::Real::zero(), |f, &val| {
+            let v = val.abs();
+            if f > v {
+                f
+            } else {
+                v
+            }
+        })
+    }
+}
+
+pub enum NormalizeAxis {
+    Row = 0,
+    Column = 1,
+}
+
+/// normalize in L2 norm
+pub fn normalize<A, S>(
+    mut m: ArrayBase<S, Ix2>,
+    axis: NormalizeAxis,
+) -> (ArrayBase<S, Ix2>, Vec<A::Real>)
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    let mut ms = Vec::new();
+    for mut v in m.axis_iter_mut(Axis(axis as usize)) {
+        let n = v.norm();
+        ms.push(n);
+        v.map_inplace(|x| *x /= A::from_real(n))
+    }
+    (m, ms)
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/operator.rs.html b/src/ndarray_linalg/operator.rs.html new file mode 100644 index 00000000..09f6af56 --- /dev/null +++ b/src/ndarray_linalg/operator.rs.html @@ -0,0 +1,190 @@ +operator.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+
//! Linear operator algebra
+
+use crate::generate::hstack;
+use crate::types::*;
+use ndarray::*;
+
+/// Abstracted linear operator as an action to vector (`ArrayBase<S, Ix1>`) and matrix
+/// (`ArrayBase<S, Ix2`)
+pub trait LinearOperator {
+    type Elem: Scalar;
+
+    /// Apply operator out-place
+    fn apply<S>(&self, a: &ArrayBase<S, Ix1>) -> Array1<S::Elem>
+    where
+        S: Data<Elem = Self::Elem>,
+    {
+        let mut a = a.to_owned();
+        self.apply_mut(&mut a);
+        a
+    }
+
+    /// Apply operator in-place
+    fn apply_mut<S>(&self, a: &mut ArrayBase<S, Ix1>)
+    where
+        S: DataMut<Elem = Self::Elem>,
+    {
+        let b = self.apply(a);
+        azip!((a in a, &b in &b) *a = b);
+    }
+
+    /// Apply operator with move
+    fn apply_into<S>(&self, mut a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix1>
+    where
+        S: DataOwned<Elem = Self::Elem> + DataMut,
+    {
+        self.apply_mut(&mut a);
+        a
+    }
+
+    /// Apply operator to matrix out-place
+    fn apply2<S>(&self, a: &ArrayBase<S, Ix2>) -> Array2<S::Elem>
+    where
+        S: Data<Elem = Self::Elem>,
+    {
+        let cols: Vec<_> = a.axis_iter(Axis(1)).map(|col| self.apply(&col)).collect();
+        hstack(&cols).unwrap()
+    }
+
+    /// Apply operator to matrix in-place
+    fn apply2_mut<S>(&self, a: &mut ArrayBase<S, Ix2>)
+    where
+        S: DataMut<Elem = Self::Elem>,
+    {
+        for mut col in a.axis_iter_mut(Axis(1)) {
+            self.apply_mut(&mut col)
+        }
+    }
+
+    /// Apply operator to matrix with move
+    fn apply2_into<S>(&self, mut a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix2>
+    where
+        S: DataOwned<Elem = Self::Elem> + DataMut,
+    {
+        self.apply2_mut(&mut a);
+        a
+    }
+}
+
+impl<A, Sa> LinearOperator for ArrayBase<Sa, Ix2>
+where
+    A: Scalar,
+    Sa: Data<Elem = A>,
+{
+    type Elem = A;
+
+    fn apply<S>(&self, a: &ArrayBase<S, Ix1>) -> Array1<A>
+    where
+        S: Data<Elem = A>,
+    {
+        self.dot(a)
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/opnorm.rs.html b/src/ndarray_linalg/opnorm.rs.html new file mode 100644 index 00000000..8d2ed7e2 --- /dev/null +++ b/src/ndarray_linalg/opnorm.rs.html @@ -0,0 +1,232 @@ +opnorm.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+
//! Operator norm
+
+use lax::Tridiagonal;
+use ndarray::*;
+
+use crate::error::*;
+use crate::layout::*;
+use crate::types::*;
+
+pub use lax::NormType;
+
+/// Operator norm using `*lange` LAPACK routines
+///
+/// [Wikipedia article on operator norm](https://en.wikipedia.org/wiki/Operator_norm)
+pub trait OperationNorm {
+    /// the value of norm
+    type Output: Scalar;
+
+    fn opnorm(&self, t: NormType) -> Result<Self::Output>;
+
+    /// the one norm of a matrix (maximum column sum)
+    fn opnorm_one(&self) -> Result<Self::Output> {
+        self.opnorm(NormType::One)
+    }
+
+    /// the infinity norm of a matrix (maximum row sum)
+    fn opnorm_inf(&self) -> Result<Self::Output> {
+        self.opnorm(NormType::Infinity)
+    }
+
+    /// the Frobenius norm of a matrix (square root of sum of squares)
+    fn opnorm_fro(&self) -> Result<Self::Output> {
+        self.opnorm(NormType::Frobenius)
+    }
+}
+
+impl<A, S> OperationNorm for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = A::Real;
+
+    fn opnorm(&self, t: NormType) -> Result<Self::Output> {
+        let l = self.layout()?;
+        let a = self.as_allocated()?;
+        Ok(A::opnorm(t, l, a))
+    }
+}
+
+impl<A> OperationNorm for Tridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    type Output = A::Real;
+
+    fn opnorm(&self, t: NormType) -> Result<Self::Output> {
+        // `self` is a tridiagonal matrix like,
+        // [d0, u1,  0,   ...,       0,
+        //  l1, d1, u2,            ...,
+        //   0, l2, d2,
+        //  ...           ...,  u{n-1},
+        //   0,  ...,  l{n-1},  d{n-1},]
+        let arr = match t {
+            // opnorm_one() calculates muximum column sum.
+            // Therefore, This part align the columns and make a (3 x n) matrix like,
+            // [ 0, u1, u2, ..., u{n-1},
+            //  d0, d1, d2, ..., d{n-1},
+            //  l1, l2, l3, ...,      0,]
+            NormType::One => {
+                let zl: Array1<A> = Array::zeros(1);
+                let zu: Array1<A> = Array::zeros(1);
+                let dl = concatenate![Axis(0), &self.dl, zl]; // n
+                let du = concatenate![Axis(0), zu, &self.du]; // n
+                stack![Axis(0), du, &self.d, dl] // 3 x n
+            }
+            // opnorm_inf() calculates muximum row sum.
+            // Therefore, This part align the rows and make a (n x 3) matrix like,
+            // [     0,     d0,     u1,
+            //      l1,     d1,     u2,
+            //      l2,     d2,     u3,
+            //     ...,    ...,    ...,
+            //  l{n-1}, d{n-1},      0,]
+            NormType::Infinity => {
+                let zl: Array1<A> = Array::zeros(1);
+                let zu: Array1<A> = Array::zeros(1);
+                let dl = concatenate![Axis(0), zl, &self.dl]; // n
+                let du = concatenate![Axis(0), &self.du, zu]; // n
+                stack![Axis(1), dl, &self.d, du] // n x 3
+            }
+            // opnorm_fro() calculates square root of sum of squares.
+            // Because it is independent of the shape of matrix,
+            // this part make a (1 x (3n-2)) matrix like,
+            // [l1, ..., l{n-1}, d0, ..., d{n-1}, u1, ..., u{n-1}]
+            NormType::Frobenius => {
+                concatenate![Axis(0), &self.dl, &self.d, &self.du].insert_axis(Axis(0))
+            }
+        };
+        let l = arr.layout()?;
+        let a = arr.as_allocated()?;
+        Ok(A::opnorm(t, l, a))
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/qr.rs.html b/src/ndarray_linalg/qr.rs.html new file mode 100644 index 00000000..43e33e1f --- /dev/null +++ b/src/ndarray_linalg/qr.rs.html @@ -0,0 +1,336 @@ +qr.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+
//! QR decomposition
+//!
+//! [Wikipedia article on QR decomposition](https://en.wikipedia.org/wiki/QR_decomposition)
+
+use ndarray::*;
+use num_traits::Zero;
+
+use crate::convert::*;
+use crate::error::*;
+use crate::layout::*;
+use crate::triangular::*;
+use crate::types::*;
+
+pub use lax::UPLO;
+
+/// QR decomposition for matrix reference
+///
+/// This creates copy due for reshaping array.
+/// To avoid copy and the matrix is square, please use `QRSquare*` traits.
+pub trait QR {
+    type Q;
+    type R;
+    fn qr(&self) -> Result<(Self::Q, Self::R)>;
+}
+
+/// QR decomposition
+///
+/// This creates copy due for reshaping array.
+/// To avoid copy and the matrix is square, please use `QRSquare*` traits.
+pub trait QRInto: Sized {
+    type Q;
+    type R;
+    fn qr_into(self) -> Result<(Self::Q, Self::R)>;
+}
+
+/// QR decomposition for square matrix reference
+pub trait QRSquare: Sized {
+    type Q;
+    type R;
+    fn qr_square(&self) -> Result<(Self::Q, Self::R)>;
+}
+
+/// QR decomposition for square matrix
+pub trait QRSquareInto: Sized {
+    type R;
+    fn qr_square_into(self) -> Result<(Self, Self::R)>;
+}
+
+/// QR decomposition for mutable reference of square matrix
+pub trait QRSquareInplace: Sized {
+    type R;
+    fn qr_square_inplace(&mut self) -> Result<(&mut Self, Self::R)>;
+}
+
+impl<A, S> QRSquareInplace for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type R = Array2<A>;
+
+    fn qr_square_inplace(&mut self) -> Result<(&mut Self, Self::R)> {
+        let l = self.square_layout()?;
+        let r = A::qr(l, self.as_allocated_mut()?)?;
+        let r: Array2<_> = into_matrix(l, r)?;
+        Ok((self, r.into_triangular(UPLO::Upper)))
+    }
+}
+
+impl<A, S> QRSquareInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type R = Array2<A>;
+
+    fn qr_square_into(mut self) -> Result<(Self, Self::R)> {
+        let (_, r) = self.qr_square_inplace()?;
+        Ok((self, r))
+    }
+}
+
+impl<A, S> QRSquare for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Q = Array2<A>;
+    type R = Array2<A>;
+
+    fn qr_square(&self) -> Result<(Self::Q, Self::R)> {
+        let a = self.to_owned();
+        a.qr_square_into()
+    }
+}
+
+impl<A, S> QRInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type Q = Array2<A>;
+    type R = Array2<A>;
+
+    fn qr_into(mut self) -> Result<(Self::Q, Self::R)> {
+        let n = self.nrows();
+        let m = self.ncols();
+        let k = ::std::cmp::min(n, m);
+        let l = self.layout()?;
+        let r = A::qr(l, self.as_allocated_mut()?)?;
+        let r: Array2<_> = into_matrix(l, r)?;
+        let q = self;
+        Ok((take_slice(&q, n, k), take_slice_upper(&r, k, m)))
+    }
+}
+
+impl<A, S> QR for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Q = Array2<A>;
+    type R = Array2<A>;
+
+    fn qr(&self) -> Result<(Self::Q, Self::R)> {
+        let a = self.to_owned();
+        a.qr_into()
+    }
+}
+
+fn take_slice<A, S1, S2>(a: &ArrayBase<S1, Ix2>, n: usize, m: usize) -> ArrayBase<S2, Ix2>
+where
+    A: Copy,
+    S1: Data<Elem = A>,
+    S2: DataMut<Elem = A> + DataOwned,
+{
+    let av = a.slice(s![..n as isize, ..m as isize]);
+    replicate(&av)
+}
+
+fn take_slice_upper<A, S1, S2>(a: &ArrayBase<S1, Ix2>, n: usize, m: usize) -> ArrayBase<S2, Ix2>
+where
+    A: Copy + Zero,
+    S1: Data<Elem = A>,
+    S2: DataMut<Elem = A> + DataOwned,
+{
+    let av = a.slice(s![..n, ..m]);
+    let mut a = replicate(&av);
+    Zip::indexed(&mut a).for_each(|(i, j), elt| {
+        if i > j {
+            *elt = A::zero()
+        }
+    });
+    a
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/solve.rs.html b/src/ndarray_linalg/solve.rs.html new file mode 100644 index 00000000..fbd2b541 --- /dev/null +++ b/src/ndarray_linalg/solve.rs.html @@ -0,0 +1,1312 @@ +solve.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+
//! Solve systems of linear equations and invert matrices
+//!
+//! # Examples
+//!
+//! Solve `A * x = b`:
+//!
+//! ```
+//! #[macro_use]
+//! extern crate ndarray;
+//! extern crate ndarray_linalg;
+//!
+//! use ndarray::prelude::*;
+//! use ndarray_linalg::Solve;
+//! # fn main() {
+//!
+//! let a: Array2<f64> = array![[3., 2., -1.], [2., -2., 4.], [-2., 1., -2.]];
+//! let b: Array1<f64> = array![1., -2., 0.];
+//! let x = a.solve_into(b).unwrap();
+//! assert!(x.abs_diff_eq(&array![1., -2., -2.], 1e-9));
+//!
+//! # }
+//! ```
+//!
+//! There are also special functions for solving `A^T * x = b` and
+//! `A^H * x = b`.
+//!
+//! If you are solving multiple systems of linear equations with the same
+//! coefficient matrix `A`, it's faster to compute the LU factorization once at
+//! the beginning than solving directly using `A`:
+//!
+//! ```
+//! # extern crate ndarray;
+//! # extern crate ndarray_linalg;
+//!
+//! use ndarray::prelude::*;
+//! use ndarray_linalg::*;
+//! # fn main() {
+//!
+//! let a: Array2<f64> = random((3, 3));
+//! let f = a.factorize_into().unwrap(); // LU factorize A (A is consumed)
+//! for _ in 0..10 {
+//!     let b: Array1<f64> = random(3);
+//!     let x = f.solve_into(b).unwrap(); // Solve A * x = b using factorized L, U
+//! }
+//!
+//! # }
+//! ```
+
+use ndarray::*;
+use num_traits::{Float, Zero};
+
+use crate::convert::*;
+use crate::error::*;
+use crate::layout::*;
+use crate::opnorm::OperationNorm;
+use crate::types::*;
+
+pub use lax::{Pivot, Transpose};
+
+/// An interface for solving systems of linear equations.
+///
+/// There are three groups of methods:
+///
+/// * `solve*` (normal) methods solve `A * x = b` for `x`.
+/// * `solve_t*` (transpose) methods solve `A^T * x = b` for `x`.
+/// * `solve_h*` (Hermitian conjugate) methods solve `A^H * x = b` for `x`.
+///
+/// Within each group, there are three methods that handle ownership differently:
+///
+/// * `*` methods take a reference to `b` and return `x` as a new array.
+/// * `*_into` methods take ownership of `b`, store the result in it, and return it.
+/// * `*_inplace` methods take a mutable reference to `b` and store the result in that array.
+///
+/// If you plan to solve many equations with the same `A` matrix but different
+/// `b` vectors, it's faster to factor the `A` matrix once using the
+/// `Factorize` trait, and then solve using the `LUFactorized` struct.
+pub trait Solve<A: Scalar> {
+    /// Solves a system of linear equations `A * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of columns
+    /// of `A`.
+    fn solve<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
+        let mut b = replicate(b);
+        self.solve_inplace(&mut b)?;
+        Ok(b)
+    }
+
+    /// Solves a system of linear equations `A * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of columns
+    /// of `A`.
+    fn solve_into<S: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<S, Ix1>,
+    ) -> Result<ArrayBase<S, Ix1>> {
+        self.solve_inplace(&mut b)?;
+        Ok(b)
+    }
+
+    /// Solves a system of linear equations `A * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of columns
+    /// of `A`.
+    fn solve_inplace<'a, S: DataMut<Elem = A>>(
+        &self,
+        b: &'a mut ArrayBase<S, Ix1>,
+    ) -> Result<&'a mut ArrayBase<S, Ix1>>;
+
+    /// Solves a system of linear equations `A^T * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of rows of
+    /// `A`.
+    fn solve_t<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
+        let mut b = replicate(b);
+        self.solve_t_inplace(&mut b)?;
+        Ok(b)
+    }
+
+    /// Solves a system of linear equations `A^T * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of rows of
+    /// `A`.
+    fn solve_t_into<S: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<S, Ix1>,
+    ) -> Result<ArrayBase<S, Ix1>> {
+        self.solve_t_inplace(&mut b)?;
+        Ok(b)
+    }
+
+    /// Solves a system of linear equations `A^T * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of rows of
+    /// `A`.
+    fn solve_t_inplace<'a, S: DataMut<Elem = A>>(
+        &self,
+        b: &'a mut ArrayBase<S, Ix1>,
+    ) -> Result<&'a mut ArrayBase<S, Ix1>>;
+
+    /// Solves a system of linear equations `A^H * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of rows of
+    /// `A`.
+    fn solve_h<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
+        let mut b = replicate(b);
+        self.solve_h_inplace(&mut b)?;
+        Ok(b)
+    }
+    /// Solves a system of linear equations `A^H * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of rows of
+    /// `A`.
+    fn solve_h_into<S: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<S, Ix1>,
+    ) -> Result<ArrayBase<S, Ix1>> {
+        self.solve_h_inplace(&mut b)?;
+        Ok(b)
+    }
+    /// Solves a system of linear equations `A^H * x = b` where `A` is `self`, `b`
+    /// is the argument, and `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of rows of
+    /// `A`.
+    fn solve_h_inplace<'a, S: DataMut<Elem = A>>(
+        &self,
+        b: &'a mut ArrayBase<S, Ix1>,
+    ) -> Result<&'a mut ArrayBase<S, Ix1>>;
+}
+
+/// Represents the LU factorization of a matrix `A` as `A = P*L*U`.
+#[derive(Clone)]
+pub struct LUFactorized<S: Data + RawDataClone> {
+    /// The factors `L` and `U`; the unit diagonal elements of `L` are not
+    /// stored.
+    a: ArrayBase<S, Ix2>,
+    /// The pivot indices that define the permutation matrix `P`.
+    ipiv: Pivot,
+}
+
+impl<A, S> Solve<A> for LUFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A> + RawDataClone,
+{
+    fn solve_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        assert_eq!(
+            rhs.len(),
+            self.a.len_of(Axis(1)),
+            "The length of `rhs` must be compatible with the shape of the factored matrix.",
+        );
+        A::solve(
+            self.a.square_layout()?,
+            Transpose::No,
+            self.a.as_allocated()?,
+            &self.ipiv,
+            rhs.as_slice_mut().unwrap(),
+        )?;
+        Ok(rhs)
+    }
+    fn solve_t_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        assert_eq!(
+            rhs.len(),
+            self.a.len_of(Axis(0)),
+            "The length of `rhs` must be compatible with the shape of the factored matrix.",
+        );
+        A::solve(
+            self.a.square_layout()?,
+            Transpose::Transpose,
+            self.a.as_allocated()?,
+            &self.ipiv,
+            rhs.as_slice_mut().unwrap(),
+        )?;
+        Ok(rhs)
+    }
+    fn solve_h_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        assert_eq!(
+            rhs.len(),
+            self.a.len_of(Axis(0)),
+            "The length of `rhs` must be compatible with the shape of the factored matrix.",
+        );
+        A::solve(
+            self.a.square_layout()?,
+            Transpose::Hermite,
+            self.a.as_allocated()?,
+            &self.ipiv,
+            rhs.as_slice_mut().unwrap(),
+        )?;
+        Ok(rhs)
+    }
+}
+
+impl<A, S> Solve<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn solve_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize()?;
+        f.solve_inplace(rhs)
+    }
+    fn solve_t_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize()?;
+        f.solve_t_inplace(rhs)
+    }
+    fn solve_h_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize()?;
+        f.solve_h_inplace(rhs)
+    }
+}
+
+/// An interface for computing LU factorizations of matrix refs.
+pub trait Factorize<S: Data + RawDataClone> {
+    /// Computes the LU factorization `A = P*L*U`, where `P` is a permutation
+    /// matrix.
+    fn factorize(&self) -> Result<LUFactorized<S>>;
+}
+
+/// An interface for computing LU factorizations of matrices.
+pub trait FactorizeInto<S: Data + RawDataClone> {
+    /// Computes the LU factorization `A = P*L*U`, where `P` is a permutation
+    /// matrix.
+    fn factorize_into(self) -> Result<LUFactorized<S>>;
+}
+
+impl<A, S> FactorizeInto<S> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A> + RawDataClone,
+{
+    fn factorize_into(mut self) -> Result<LUFactorized<S>> {
+        let ipiv = A::lu(self.layout()?, self.as_allocated_mut()?)?;
+        Ok(LUFactorized { a: self, ipiv })
+    }
+}
+
+impl<A, Si> Factorize<OwnedRepr<A>> for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+{
+    fn factorize(&self) -> Result<LUFactorized<OwnedRepr<A>>> {
+        let mut a: Array2<A> = replicate(self);
+        let ipiv = A::lu(a.layout()?, a.as_allocated_mut()?)?;
+        Ok(LUFactorized { a, ipiv })
+    }
+}
+
+/// An interface for inverting matrix refs.
+pub trait Inverse {
+    type Output;
+    /// Computes the inverse of the matrix.
+    fn inv(&self) -> Result<Self::Output>;
+}
+
+/// An interface for inverting matrices.
+pub trait InverseInto {
+    type Output;
+    /// Computes the inverse of the matrix.
+    fn inv_into(self) -> Result<Self::Output>;
+}
+
+impl<A, S> InverseInto for LUFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A> + RawDataClone,
+{
+    type Output = ArrayBase<S, Ix2>;
+
+    fn inv_into(mut self) -> Result<ArrayBase<S, Ix2>> {
+        A::inv(
+            self.a.square_layout()?,
+            self.a.as_allocated_mut()?,
+            &self.ipiv,
+        )?;
+        Ok(self.a)
+    }
+}
+
+impl<A, S> Inverse for LUFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A> + RawDataClone,
+{
+    type Output = Array2<A>;
+
+    fn inv(&self) -> Result<Array2<A>> {
+        // Preserve the existing layout. This is required to obtain the correct
+        // result, because the result of `A::inv` is layout-dependent.
+        let a = if self.a.is_standard_layout() {
+            replicate(&self.a)
+        } else {
+            replicate(&self.a.t()).reversed_axes()
+        };
+        let f = LUFactorized {
+            a,
+            ipiv: self.ipiv.clone(),
+        };
+        f.inv_into()
+    }
+}
+
+impl<A, S> InverseInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A> + RawDataClone,
+{
+    type Output = Self;
+
+    fn inv_into(self) -> Result<Self::Output> {
+        let f = self.factorize_into()?;
+        f.inv_into()
+    }
+}
+
+impl<A, Si> Inverse for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+{
+    type Output = Array2<A>;
+
+    fn inv(&self) -> Result<Self::Output> {
+        let f = self.factorize()?;
+        f.inv_into()
+    }
+}
+
+/// An interface for calculating determinants of matrix refs.
+pub trait Determinant<A: Scalar> {
+    /// Computes the determinant of the matrix.
+    fn det(&self) -> Result<A> {
+        let (sign, ln_det) = self.sln_det()?;
+        Ok(sign * A::from_real(Float::exp(ln_det)))
+    }
+
+    /// Computes the `(sign, natural_log)` of the determinant of the matrix.
+    ///
+    /// For real matrices, `sign` is `1`, `0`, or `-1`. For complex matrices,
+    /// `sign` is `0` or a complex number with absolute value 1. The
+    /// `natural_log` is the natural logarithm of the absolute value of the
+    /// determinant. If the determinant is zero, `sign` is 0 and `natural_log`
+    /// is negative infinity.
+    ///
+    /// To obtain the determinant, you can compute `sign * natural_log.exp()`
+    /// or just call `.det()` instead.
+    ///
+    /// This method is more robust than `.det()` to very small or very large
+    /// determinants since it returns the natural logarithm of the determinant
+    /// rather than the determinant itself.
+    fn sln_det(&self) -> Result<(A, A::Real)>;
+}
+
+/// An interface for calculating determinants of matrices.
+pub trait DeterminantInto<A: Scalar>: Sized {
+    /// Computes the determinant of the matrix.
+    fn det_into(self) -> Result<A> {
+        let (sign, ln_det) = self.sln_det_into()?;
+        Ok(sign * A::from_real(Float::exp(ln_det)))
+    }
+
+    /// Computes the `(sign, natural_log)` of the determinant of the matrix.
+    ///
+    /// For real matrices, `sign` is `1`, `0`, or `-1`. For complex matrices,
+    /// `sign` is `0` or a complex number with absolute value 1. The
+    /// `natural_log` is the natural logarithm of the absolute value of the
+    /// determinant. If the determinant is zero, `sign` is 0 and `natural_log`
+    /// is negative infinity.
+    ///
+    /// To obtain the determinant, you can compute `sign * natural_log.exp()`
+    /// or just call `.det_into()` instead.
+    ///
+    /// This method is more robust than `.det()` to very small or very large
+    /// determinants since it returns the natural logarithm of the determinant
+    /// rather than the determinant itself.
+    fn sln_det_into(self) -> Result<(A, A::Real)>;
+}
+
+fn lu_sln_det<'a, A, P, U>(ipiv_iter: P, u_diag_iter: U) -> (A, A::Real)
+where
+    A: Scalar + Lapack,
+    P: Iterator<Item = i32>,
+    U: Iterator<Item = &'a A>,
+{
+    let pivot_sign = if ipiv_iter
+        .enumerate()
+        .filter(|&(i, pivot)| pivot != i as i32 + 1)
+        .count()
+        % 2
+        == 0
+    {
+        A::one()
+    } else {
+        -A::one()
+    };
+    let (upper_sign, ln_det) = u_diag_iter.fold(
+        (A::one(), A::Real::zero()),
+        |(upper_sign, ln_det), &elem| {
+            let abs_elem: A::Real = elem.abs();
+            (
+                upper_sign * elem / A::from_real(abs_elem),
+                ln_det + Float::ln(abs_elem),
+            )
+        },
+    );
+    (pivot_sign * upper_sign, ln_det)
+}
+
+impl<A, S> Determinant<A> for LUFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A> + RawDataClone,
+{
+    fn sln_det(&self) -> Result<(A, A::Real)> {
+        self.a.ensure_square()?;
+        Ok(lu_sln_det(self.ipiv.iter().cloned(), self.a.diag().iter()))
+    }
+}
+
+impl<A, S> DeterminantInto<A> for LUFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A> + RawDataClone,
+{
+    fn sln_det_into(self) -> Result<(A, A::Real)> {
+        self.a.ensure_square()?;
+        Ok(lu_sln_det(self.ipiv.into_iter(), self.a.into_diag().iter()))
+    }
+}
+
+impl<A, S> Determinant<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn sln_det(&self) -> Result<(A, A::Real)> {
+        self.ensure_square()?;
+        match self.factorize() {
+            Ok(fac) => fac.sln_det(),
+            Err(LinalgError::Lapack(e))
+                if matches!(e, lax::error::Error::LapackComputationalFailure { .. }) =>
+            {
+                // The determinant is zero.
+                Ok((A::zero(), A::Real::neg_infinity()))
+            }
+            Err(err) => Err(err),
+        }
+    }
+}
+
+impl<A, S> DeterminantInto<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A> + RawDataClone,
+{
+    fn sln_det_into(self) -> Result<(A, A::Real)> {
+        self.ensure_square()?;
+        match self.factorize_into() {
+            Ok(fac) => fac.sln_det_into(),
+            Err(LinalgError::Lapack(e))
+                if matches!(e, lax::error::Error::LapackComputationalFailure { .. }) =>
+            {
+                // The determinant is zero.
+                Ok((A::zero(), A::Real::neg_infinity()))
+            }
+            Err(err) => Err(err),
+        }
+    }
+}
+
+/// An interface for *estimating* the reciprocal condition number of matrix refs.
+pub trait ReciprocalConditionNum<A: Scalar> {
+    /// *Estimates* the reciprocal of the condition number of the matrix in
+    /// 1-norm.
+    ///
+    /// This method uses the LAPACK `*gecon` routines, which *estimate*
+    /// `self.inv().opnorm_one()` and then compute `rcond = 1. /
+    /// (self.opnorm_one() * self.inv().opnorm_one())`.
+    ///
+    /// * If `rcond` is near `0.`, the matrix is badly conditioned.
+    /// * If `rcond` is near `1.`, the matrix is well conditioned.
+    fn rcond(&self) -> Result<A::Real>;
+}
+
+/// An interface for *estimating* the reciprocal condition number of matrices.
+pub trait ReciprocalConditionNumInto<A: Scalar> {
+    /// *Estimates* the reciprocal of the condition number of the matrix in
+    /// 1-norm.
+    ///
+    /// This method uses the LAPACK `*gecon` routines, which *estimate*
+    /// `self.inv().opnorm_one()` and then compute `rcond = 1. /
+    /// (self.opnorm_one() * self.inv().opnorm_one())`.
+    ///
+    /// * If `rcond` is near `0.`, the matrix is badly conditioned.
+    /// * If `rcond` is near `1.`, the matrix is well conditioned.
+    fn rcond_into(self) -> Result<A::Real>;
+}
+
+impl<A, S> ReciprocalConditionNum<A> for LUFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A> + RawDataClone,
+{
+    fn rcond(&self) -> Result<A::Real> {
+        Ok(A::rcond(
+            self.a.layout()?,
+            self.a.as_allocated()?,
+            self.a.opnorm_one()?,
+        )?)
+    }
+}
+
+impl<A, S> ReciprocalConditionNumInto<A> for LUFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A> + RawDataClone,
+{
+    fn rcond_into(self) -> Result<A::Real> {
+        self.rcond()
+    }
+}
+
+impl<A, S> ReciprocalConditionNum<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn rcond(&self) -> Result<A::Real> {
+        self.factorize()?.rcond_into()
+    }
+}
+
+impl<A, S> ReciprocalConditionNumInto<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A> + RawDataClone,
+{
+    fn rcond_into(self) -> Result<A::Real> {
+        self.factorize_into()?.rcond_into()
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/solveh.rs.html b/src/ndarray_linalg/solveh.rs.html new file mode 100644 index 00000000..5f4a881b --- /dev/null +++ b/src/ndarray_linalg/solveh.rs.html @@ -0,0 +1,998 @@ +solveh.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+
//! Solve Hermitian (or real symmetric) linear problems and invert Hermitian
+//! (or real symmetric) matrices
+//!
+//! **Note that only the upper triangular portion of the matrix is used.**
+//!
+//! # Examples
+//!
+//! Solve `A * x = b`, where `A` is a Hermitian (or real symmetric) matrix:
+//!
+//! ```
+//! #[macro_use]
+//! extern crate ndarray;
+//! extern crate ndarray_linalg;
+//!
+//! use ndarray::prelude::*;
+//! use ndarray_linalg::SolveH;
+//! # fn main() {
+//!
+//! let a: Array2<f64> = array![
+//!     [3., 2., -1.],
+//!     [2., -2., 4.],
+//!     [-1., 4., 5.]
+//! ];
+//! let b: Array1<f64> = array![11., -12., 1.];
+//! let x = a.solveh_into(b).unwrap();
+//! assert!(x.abs_diff_eq(&array![1., 3., -2.], 1e-9));
+//!
+//! # }
+//! ```
+//!
+//! If you are solving multiple systems of linear equations with the same
+//! Hermitian or real symmetric coefficient matrix `A`, it's faster to compute
+//! the factorization once at the beginning than solving directly using `A`:
+//!
+//! ```
+//! # extern crate ndarray;
+//! # extern crate ndarray_linalg;
+//! use ndarray::prelude::*;
+//! use ndarray_linalg::*;
+//! # fn main() {
+//!
+//! let a: Array2<f64> = random((3, 3));
+//! let f = a.factorizeh_into().unwrap(); // Factorize A (A is consumed)
+//! for _ in 0..10 {
+//!     let b: Array1<f64> = random(3);
+//!     let x = f.solveh_into(b).unwrap(); // Solve A * x = b using the factorization
+//! }
+//!
+//! # }
+//! ```
+
+use ndarray::*;
+use num_traits::{Float, One, Zero};
+
+use crate::convert::*;
+use crate::error::*;
+use crate::layout::*;
+use crate::types::*;
+
+pub use lax::{Pivot, UPLO};
+
+/// An interface for solving systems of Hermitian (or real symmetric) linear equations.
+///
+/// If you plan to solve many equations with the same Hermitian (or real
+/// symmetric) coefficient matrix `A` but different `b` vectors, it's faster to
+/// factor the `A` matrix once using the `FactorizeH` trait, and then solve
+/// using the `BKFactorized` struct.
+pub trait SolveH<A: Scalar> {
+    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
+    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of columns
+    /// of `A`.
+    fn solveh<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
+        let mut b = replicate(b);
+        self.solveh_inplace(&mut b)?;
+        Ok(b)
+    }
+
+    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
+    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of columns
+    /// of `A`.
+    fn solveh_into<S: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<S, Ix1>,
+    ) -> Result<ArrayBase<S, Ix1>> {
+        self.solveh_inplace(&mut b)?;
+        Ok(b)
+    }
+
+    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
+    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result. The value of `x` is also assigned to the
+    /// argument.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the length of `b` is not the equal to the number of columns
+    /// of `A`.
+    fn solveh_inplace<'a, S: DataMut<Elem = A>>(
+        &self,
+        b: &'a mut ArrayBase<S, Ix1>,
+    ) -> Result<&'a mut ArrayBase<S, Ix1>>;
+}
+
+/// Represents the Bunch–Kaufman factorization of a Hermitian (or real
+/// symmetric) matrix as `A = P * U * D * U^H * P^T`.
+pub struct BKFactorized<S: Data> {
+    pub a: ArrayBase<S, Ix2>,
+    pub ipiv: Pivot,
+}
+
+impl<A, S> SolveH<A> for BKFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn solveh_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        assert_eq!(
+            rhs.len(),
+            self.a.len_of(Axis(1)),
+            "The length of `rhs` must be compatible with the shape of the factored matrix.",
+        );
+        A::solveh(
+            self.a.square_layout()?,
+            UPLO::Upper,
+            self.a.as_allocated()?,
+            &self.ipiv,
+            rhs.as_slice_mut().unwrap(),
+        )?;
+        Ok(rhs)
+    }
+}
+
+impl<A, S> SolveH<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn solveh_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix1>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix1>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorizeh()?;
+        f.solveh_inplace(rhs)
+    }
+}
+
+/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
+/// real symmetric) matrix refs.
+pub trait FactorizeH<S: Data> {
+    /// Computes the Bunch–Kaufman factorization of a Hermitian (or real
+    /// symmetric) matrix.
+    fn factorizeh(&self) -> Result<BKFactorized<S>>;
+}
+
+/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
+/// real symmetric) matrices.
+pub trait FactorizeHInto<S: Data> {
+    /// Computes the Bunch–Kaufman factorization of a Hermitian (or real
+    /// symmetric) matrix.
+    fn factorizeh_into(self) -> Result<BKFactorized<S>>;
+}
+
+impl<A, S> FactorizeHInto<S> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    fn factorizeh_into(mut self) -> Result<BKFactorized<S>> {
+        let ipiv = A::bk(self.square_layout()?, UPLO::Upper, self.as_allocated_mut()?)?;
+        Ok(BKFactorized { a: self, ipiv })
+    }
+}
+
+impl<A, Si> FactorizeH<OwnedRepr<A>> for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+{
+    fn factorizeh(&self) -> Result<BKFactorized<OwnedRepr<A>>> {
+        let mut a: Array2<A> = replicate(self);
+        let ipiv = A::bk(a.square_layout()?, UPLO::Upper, a.as_allocated_mut()?)?;
+        Ok(BKFactorized { a, ipiv })
+    }
+}
+
+/// An interface for inverting Hermitian (or real symmetric) matrix refs.
+pub trait InverseH {
+    type Output;
+    /// Computes the inverse of the Hermitian (or real symmetric) matrix.
+    fn invh(&self) -> Result<Self::Output>;
+}
+
+/// An interface for inverting Hermitian (or real symmetric) matrices.
+pub trait InverseHInto {
+    type Output;
+    /// Computes the inverse of the Hermitian (or real symmetric) matrix.
+    fn invh_into(self) -> Result<Self::Output>;
+}
+
+impl<A, S> InverseHInto for BKFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type Output = ArrayBase<S, Ix2>;
+
+    fn invh_into(mut self) -> Result<ArrayBase<S, Ix2>> {
+        A::invh(
+            self.a.square_layout()?,
+            UPLO::Upper,
+            self.a.as_allocated_mut()?,
+            &self.ipiv,
+        )?;
+        triangular_fill_hermitian(&mut self.a, UPLO::Upper);
+        Ok(self.a)
+    }
+}
+
+impl<A, S> InverseH for BKFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Output = Array2<A>;
+
+    fn invh(&self) -> Result<Self::Output> {
+        let f = BKFactorized {
+            a: replicate(&self.a),
+            ipiv: self.ipiv.clone(),
+        };
+        f.invh_into()
+    }
+}
+
+impl<A, S> InverseHInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type Output = Self;
+
+    fn invh_into(self) -> Result<Self::Output> {
+        let f = self.factorizeh_into()?;
+        f.invh_into()
+    }
+}
+
+impl<A, Si> InverseH for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+{
+    type Output = Array2<A>;
+
+    fn invh(&self) -> Result<Self::Output> {
+        let f = self.factorizeh()?;
+        f.invh_into()
+    }
+}
+
+/// An interface for calculating determinants of Hermitian (or real symmetric) matrix refs.
+pub trait DeterminantH {
+    /// The element type of the matrix.
+    type Elem: Scalar;
+
+    /// Computes the determinant of the Hermitian (or real symmetric) matrix.
+    fn deth(&self) -> Result<<Self::Elem as Scalar>::Real>;
+
+    /// Computes the `(sign, natural_log)` of the determinant of the Hermitian
+    /// (or real symmetric) matrix.
+    ///
+    /// The `natural_log` is the natural logarithm of the absolute value of the
+    /// determinant. If the determinant is zero, `sign` is 0 and `natural_log`
+    /// is negative infinity.
+    ///
+    /// To obtain the determinant, you can compute `sign * natural_log.exp()`
+    /// or just call `.deth()` instead.
+    ///
+    /// This method is more robust than `.deth()` to very small or very large
+    /// determinants since it returns the natural logarithm of the determinant
+    /// rather than the determinant itself.
+    fn sln_deth(&self) -> Result<(<Self::Elem as Scalar>::Real, <Self::Elem as Scalar>::Real)>;
+}
+
+/// An interface for calculating determinants of Hermitian (or real symmetric) matrices.
+pub trait DeterminantHInto {
+    /// The element type of the matrix.
+    type Elem: Scalar;
+
+    /// Computes the determinant of the Hermitian (or real symmetric) matrix.
+    fn deth_into(self) -> Result<<Self::Elem as Scalar>::Real>;
+
+    /// Computes the `(sign, natural_log)` of the determinant of the Hermitian
+    /// (or real symmetric) matrix.
+    ///
+    /// The `natural_log` is the natural logarithm of the absolute value of the
+    /// determinant. If the determinant is zero, `sign` is 0 and `natural_log`
+    /// is negative infinity.
+    ///
+    /// To obtain the determinant, you can compute `sign * natural_log.exp()`
+    /// or just call `.deth_into()` instead.
+    ///
+    /// This method is more robust than `.deth_into()` to very small or very
+    /// large determinants since it returns the natural logarithm of the
+    /// determinant rather than the determinant itself.
+    fn sln_deth_into(self) -> Result<(<Self::Elem as Scalar>::Real, <Self::Elem as Scalar>::Real)>;
+}
+
+/// Returns the sign and natural log of the determinant.
+fn bk_sln_det<P, S, A>(uplo: UPLO, ipiv_iter: P, a: &ArrayBase<S, Ix2>) -> (A::Real, A::Real)
+where
+    P: Iterator<Item = i32>,
+    S: Data<Elem = A>,
+    A: Scalar + Lapack,
+{
+    let layout = a.layout().unwrap();
+    let mut sign = A::Real::one();
+    let mut ln_det = A::Real::zero();
+    let mut ipiv_enum = ipiv_iter.enumerate();
+    while let Some((k, ipiv_k)) = ipiv_enum.next() {
+        debug_assert!(k < a.nrows() && k < a.ncols());
+        if ipiv_k > 0 {
+            // 1x1 block at k, must be real.
+            let elem = unsafe { a.uget((k, k)) }.re();
+            debug_assert_eq!(elem.im(), Zero::zero());
+            sign *= elem.signum();
+            ln_det += Float::ln(Float::abs(elem));
+        } else {
+            // 2x2 block at k..k+2.
+
+            // Upper left diagonal elem, must be real.
+            let upper_diag = unsafe { a.uget((k, k)) }.re();
+            debug_assert_eq!(upper_diag.im(), Zero::zero());
+
+            // Lower right diagonal elem, must be real.
+            let lower_diag = unsafe { a.uget((k + 1, k + 1)) }.re();
+            debug_assert_eq!(lower_diag.im(), Zero::zero());
+
+            // Off-diagonal elements, can be complex.
+            let off_diag = match layout {
+                MatrixLayout::C { .. } => match uplo {
+                    UPLO::Upper => unsafe { a.uget((k + 1, k)) },
+                    UPLO::Lower => unsafe { a.uget((k, k + 1)) },
+                },
+                MatrixLayout::F { .. } => match uplo {
+                    UPLO::Upper => unsafe { a.uget((k, k + 1)) },
+                    UPLO::Lower => unsafe { a.uget((k + 1, k)) },
+                },
+            };
+
+            // Determinant of 2x2 block.
+            let block_det = upper_diag * lower_diag - off_diag.square();
+            sign *= block_det.signum();
+            ln_det += Float::ln(Float::abs(block_det));
+
+            // Skip the k+1 ipiv value.
+            ipiv_enum.next();
+        }
+    }
+    (sign, ln_det)
+}
+
+impl<A, S> BKFactorized<S>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    /// Computes the determinant of the factorized Hermitian (or real
+    /// symmetric) matrix.
+    pub fn deth(&self) -> A::Real {
+        let (sign, ln_det) = self.sln_deth();
+        sign * Float::exp(ln_det)
+    }
+
+    /// Computes the `(sign, natural_log)` of the determinant of the factorized
+    /// Hermitian (or real symmetric) matrix.
+    ///
+    /// The `natural_log` is the natural logarithm of the absolute value of the
+    /// determinant. If the determinant is zero, `sign` is 0 and `natural_log`
+    /// is negative infinity.
+    ///
+    /// To obtain the determinant, you can compute `sign * natural_log.exp()`
+    /// or just call `.deth()` instead.
+    ///
+    /// This method is more robust than `.deth()` to very small or very large
+    /// determinants since it returns the natural logarithm of the determinant
+    /// rather than the determinant itself.
+    pub fn sln_deth(&self) -> (A::Real, A::Real) {
+        bk_sln_det(UPLO::Upper, self.ipiv.iter().cloned(), &self.a)
+    }
+
+    /// Computes the determinant of the factorized Hermitian (or real
+    /// symmetric) matrix.
+    pub fn deth_into(self) -> A::Real {
+        let (sign, ln_det) = self.sln_deth_into();
+        sign * Float::exp(ln_det)
+    }
+
+    /// Computes the `(sign, natural_log)` of the determinant of the factorized
+    /// Hermitian (or real symmetric) matrix.
+    ///
+    /// The `natural_log` is the natural logarithm of the absolute value of the
+    /// determinant. If the determinant is zero, `sign` is 0 and `natural_log`
+    /// is negative infinity.
+    ///
+    /// To obtain the determinant, you can compute `sign * natural_log.exp()`
+    /// or just call `.deth_into()` instead.
+    ///
+    /// This method is more robust than `.deth_into()` to very small or very
+    /// large determinants since it returns the natural logarithm of the
+    /// determinant rather than the determinant itself.
+    pub fn sln_deth_into(self) -> (A::Real, A::Real) {
+        bk_sln_det(UPLO::Upper, self.ipiv.into_iter(), &self.a)
+    }
+}
+
+impl<A, S> DeterminantH for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type Elem = A;
+
+    fn deth(&self) -> Result<A::Real> {
+        let (sign, ln_det) = self.sln_deth()?;
+        Ok(sign * Float::exp(ln_det))
+    }
+
+    fn sln_deth(&self) -> Result<(A::Real, A::Real)> {
+        match self.factorizeh() {
+            Ok(fac) => Ok(fac.sln_deth()),
+            Err(LinalgError::Lapack(e))
+                if matches!(e, lax::error::Error::LapackComputationalFailure { .. }) =>
+            {
+                // Determinant is zero.
+                Ok((A::Real::zero(), A::Real::neg_infinity()))
+            }
+            Err(err) => Err(err),
+        }
+    }
+}
+
+impl<A, S> DeterminantHInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type Elem = A;
+
+    fn deth_into(self) -> Result<A::Real> {
+        let (sign, ln_det) = self.sln_deth_into()?;
+        Ok(sign * Float::exp(ln_det))
+    }
+
+    fn sln_deth_into(self) -> Result<(A::Real, A::Real)> {
+        match self.factorizeh_into() {
+            Ok(fac) => Ok(fac.sln_deth_into()),
+            Err(LinalgError::Lapack(e))
+                if matches!(e, lax::error::Error::LapackComputationalFailure { .. }) =>
+            {
+                // Determinant is zero.
+                Ok((A::Real::zero(), A::Real::neg_infinity()))
+            }
+            Err(err) => Err(err),
+        }
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/svd.rs.html b/src/ndarray_linalg/svd.rs.html new file mode 100644 index 00000000..30c90dc9 --- /dev/null +++ b/src/ndarray_linalg/svd.rs.html @@ -0,0 +1,238 @@ +svd.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+
//! Singular-value decomposition (SVD)
+//!
+//! [Wikipedia article on SVD](https://en.wikipedia.org/wiki/Singular_value_decomposition)
+
+use crate::{convert::*, error::*, layout::*, types::*};
+use ndarray::*;
+
+/// singular-value decomposition of matrix reference
+pub trait SVD {
+    type U;
+    type VT;
+    type Sigma;
+    fn svd(
+        &self,
+        calc_u: bool,
+        calc_vt: bool,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
+}
+
+/// singular-value decomposition
+pub trait SVDInto {
+    type U;
+    type VT;
+    type Sigma;
+    fn svd_into(
+        self,
+        calc_u: bool,
+        calc_vt: bool,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
+}
+
+/// singular-value decomposition for mutable reference of matrix
+pub trait SVDInplace {
+    type U;
+    type VT;
+    type Sigma;
+    fn svd_inplace(
+        &mut self,
+        calc_u: bool,
+        calc_vt: bool,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
+}
+
+impl<A, S> SVDInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type U = Array2<A>;
+    type VT = Array2<A>;
+    type Sigma = Array1<A::Real>;
+
+    fn svd_into(
+        mut self,
+        calc_u: bool,
+        calc_vt: bool,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
+        self.svd_inplace(calc_u, calc_vt)
+    }
+}
+
+impl<A, S> SVD for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type U = Array2<A>;
+    type VT = Array2<A>;
+    type Sigma = Array1<A::Real>;
+
+    fn svd(
+        &self,
+        calc_u: bool,
+        calc_vt: bool,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
+        let a = self.to_owned();
+        a.svd_into(calc_u, calc_vt)
+    }
+}
+
+impl<A, S> SVDInplace for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type U = Array2<A>;
+    type VT = Array2<A>;
+    type Sigma = Array1<A::Real>;
+
+    fn svd_inplace(
+        &mut self,
+        calc_u: bool,
+        calc_vt: bool,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
+        let l = self.layout()?;
+        let svd_res = A::svd(l, calc_u, calc_vt, self.as_allocated_mut()?)?;
+        let (n, m) = l.size();
+
+        let u = svd_res.u.map(|u| into_matrix(l.resized(n, n), u).unwrap());
+        let vt = svd_res
+            .vt
+            .map(|vt| into_matrix(l.resized(m, m), vt).unwrap());
+        let s = ArrayBase::from(svd_res.s);
+        Ok((u, s, vt))
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/svddc.rs.html b/src/ndarray_linalg/svddc.rs.html new file mode 100644 index 00000000..366f798d --- /dev/null +++ b/src/ndarray_linalg/svddc.rs.html @@ -0,0 +1,234 @@ +svddc.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+
//! Singular-value decomposition (SVD) by divide-and-conquer (?gesdd)
+
+use super::{convert::*, error::*, layout::*, types::*};
+use ndarray::*;
+
+pub use lax::UVTFlag;
+
+/// Singular-value decomposition of matrix (copying) by divide-and-conquer
+pub trait SVDDC {
+    type U;
+    type VT;
+    type Sigma;
+    fn svddc(&self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
+}
+
+/// Singular-value decomposition of matrix by divide-and-conquer
+pub trait SVDDCInto {
+    type U;
+    type VT;
+    type Sigma;
+    fn svddc_into(
+        self,
+        uvt_flag: UVTFlag,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
+}
+
+/// Singular-value decomposition of matrix reference by divide-and-conquer
+pub trait SVDDCInplace {
+    type U;
+    type VT;
+    type Sigma;
+    fn svddc_inplace(
+        &mut self,
+        uvt_flag: UVTFlag,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
+}
+
+impl<A, S> SVDDC for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    type U = Array2<A>;
+    type VT = Array2<A>;
+    type Sigma = Array1<A::Real>;
+
+    fn svddc(&self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
+        self.to_owned().svddc_into(uvt_flag)
+    }
+}
+
+impl<A, S> SVDDCInto for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type U = Array2<A>;
+    type VT = Array2<A>;
+    type Sigma = Array1<A::Real>;
+
+    fn svddc_into(
+        mut self,
+        uvt_flag: UVTFlag,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
+        self.svddc_inplace(uvt_flag)
+    }
+}
+
+impl<A, S> SVDDCInplace for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: DataMut<Elem = A>,
+{
+    type U = Array2<A>;
+    type VT = Array2<A>;
+    type Sigma = Array1<A::Real>;
+
+    fn svddc_inplace(
+        &mut self,
+        uvt_flag: UVTFlag,
+    ) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
+        let l = self.layout()?;
+        let svd_res = A::svddc(l, uvt_flag, self.as_allocated_mut()?)?;
+        let (m, n) = l.size();
+        let k = m.min(n);
+
+        let (u_col, vt_row) = match uvt_flag {
+            UVTFlag::Full => (m, n),
+            UVTFlag::Some => (k, k),
+            UVTFlag::None => (0, 0),
+        };
+
+        let u = svd_res
+            .u
+            .map(|u| into_matrix(l.resized(m, u_col), u).unwrap());
+
+        let vt = svd_res
+            .vt
+            .map(|vt| into_matrix(l.resized(vt_row, n), vt).unwrap());
+
+        let s = ArrayBase::from(svd_res.s);
+        Ok((u, s, vt))
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/trace.rs.html b/src/ndarray_linalg/trace.rs.html new file mode 100644 index 00000000..7a1d0e92 --- /dev/null +++ b/src/ndarray_linalg/trace.rs.html @@ -0,0 +1,88 @@ +trace.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+
//! Trace calculation
+
+use ndarray::*;
+use std::iter::Sum;
+
+use super::error::*;
+use super::types::*;
+
+pub trait Trace {
+    type Output;
+    fn trace(&self) -> Result<Self::Output>;
+}
+
+impl<A, S> Trace for ArrayBase<S, Ix2>
+where
+    A: Scalar + Sum,
+    S: Data<Elem = A>,
+{
+    type Output = A;
+
+    fn trace(&self) -> Result<Self::Output> {
+        let n = match self.is_square() {
+            true => Ok(self.nrows()),
+            false => Err(LinalgError::NotSquare {
+                rows: self.nrows() as i32,
+                cols: self.ncols() as i32,
+            }),
+        }?;
+        Ok((0..n as usize).map(|i| self[(i, i)]).sum())
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/triangular.rs.html b/src/ndarray_linalg/triangular.rs.html new file mode 100644 index 00000000..8d74f221 --- /dev/null +++ b/src/ndarray_linalg/triangular.rs.html @@ -0,0 +1,394 @@ +triangular.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+
//! Methods for triangular matrices
+
+use lax::*;
+use ndarray::*;
+use num_traits::Zero;
+
+use super::convert::*;
+use super::error::*;
+use super::layout::*;
+use super::types::*;
+
+pub use lax::Diag;
+
+/// solve a triangular system with upper triangular matrix
+pub trait SolveTriangular<A, S, D>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+    D: Dimension,
+{
+    fn solve_triangular(&self, uplo: UPLO, diag: Diag, b: &ArrayBase<S, D>) -> Result<Array<A, D>>;
+}
+
+/// solve a triangular system with upper triangular matrix
+pub trait SolveTriangularInto<S, D>
+where
+    S: DataMut,
+    D: Dimension,
+{
+    fn solve_triangular_into(
+        &self,
+        uplo: UPLO,
+        diag: Diag,
+        b: ArrayBase<S, D>,
+    ) -> Result<ArrayBase<S, D>>;
+}
+
+/// solve a triangular system with upper triangular matrix
+pub trait SolveTriangularInplace<S, D>
+where
+    S: DataMut,
+    D: Dimension,
+{
+    fn solve_triangular_inplace<'a>(
+        &self,
+        uplo: UPLO,
+        diag: Diag,
+        b: &'a mut ArrayBase<S, D>,
+    ) -> Result<&'a mut ArrayBase<S, D>>;
+}
+
+impl<A, Si, So> SolveTriangularInto<So, Ix2> for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+    So: DataMut<Elem = A> + DataOwned,
+{
+    fn solve_triangular_into(
+        &self,
+        uplo: UPLO,
+        diag: Diag,
+        mut b: ArrayBase<So, Ix2>,
+    ) -> Result<ArrayBase<So, Ix2>> {
+        self.solve_triangular_inplace(uplo, diag, &mut b)?;
+        Ok(b)
+    }
+}
+
+impl<A, Si, So> SolveTriangularInplace<So, Ix2> for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+    So: DataMut<Elem = A> + DataOwned,
+{
+    fn solve_triangular_inplace<'a>(
+        &self,
+        uplo: UPLO,
+        diag: Diag,
+        b: &'a mut ArrayBase<So, Ix2>,
+    ) -> Result<&'a mut ArrayBase<So, Ix2>> {
+        let la = self.layout()?;
+        let a_ = self.as_allocated()?;
+        let lb = b.layout()?;
+        if !la.same_order(&lb) {
+            transpose_data(b)?;
+        }
+        let lb = b.layout()?;
+        A::solve_triangular(la, lb, uplo, diag, a_, b.as_allocated_mut()?)?;
+        Ok(b)
+    }
+}
+
+impl<A, Si, So> SolveTriangular<A, So, Ix2> for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+    So: DataMut<Elem = A> + DataOwned,
+{
+    fn solve_triangular(
+        &self,
+        uplo: UPLO,
+        diag: Diag,
+        b: &ArrayBase<So, Ix2>,
+    ) -> Result<Array2<A>> {
+        let b = replicate(b);
+        self.solve_triangular_into(uplo, diag, b)
+    }
+}
+
+impl<A, Si, So> SolveTriangularInto<So, Ix1> for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+    So: DataMut<Elem = A> + DataOwned,
+{
+    fn solve_triangular_into(
+        &self,
+        uplo: UPLO,
+        diag: Diag,
+        b: ArrayBase<So, Ix1>,
+    ) -> Result<ArrayBase<So, Ix1>> {
+        let b = into_col(b);
+        let b = self.solve_triangular_into(uplo, diag, b)?;
+        Ok(flatten(b))
+    }
+}
+
+impl<A, Si, So> SolveTriangular<A, So, Ix1> for ArrayBase<Si, Ix2>
+where
+    A: Scalar + Lapack,
+    Si: Data<Elem = A>,
+    So: DataMut<Elem = A> + DataOwned,
+{
+    fn solve_triangular(
+        &self,
+        uplo: UPLO,
+        diag: Diag,
+        b: &ArrayBase<So, Ix1>,
+    ) -> Result<Array1<A>> {
+        let b = b.to_owned();
+        self.solve_triangular_into(uplo, diag, b)
+    }
+}
+
+pub trait IntoTriangular<T> {
+    fn into_triangular(self, uplo: UPLO) -> T;
+}
+
+impl<'a, A, S> IntoTriangular<&'a mut ArrayBase<S, Ix2>> for &'a mut ArrayBase<S, Ix2>
+where
+    A: Zero,
+    S: DataMut<Elem = A>,
+{
+    fn into_triangular(self, uplo: UPLO) -> &'a mut ArrayBase<S, Ix2> {
+        match uplo {
+            UPLO::Upper => {
+                for ((i, j), val) in self.indexed_iter_mut() {
+                    if i > j {
+                        *val = A::zero();
+                    }
+                }
+            }
+            UPLO::Lower => {
+                for ((i, j), val) in self.indexed_iter_mut() {
+                    if i < j {
+                        *val = A::zero();
+                    }
+                }
+            }
+        }
+        self
+    }
+}
+
+impl<A, S> IntoTriangular<ArrayBase<S, Ix2>> for ArrayBase<S, Ix2>
+where
+    A: Zero,
+    S: DataMut<Elem = A>,
+{
+    fn into_triangular(mut self, uplo: UPLO) -> ArrayBase<S, Ix2> {
+        (&mut self).into_triangular(uplo);
+        self
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/tridiagonal.rs.html b/src/ndarray_linalg/tridiagonal.rs.html new file mode 100644 index 00000000..2189ed27 --- /dev/null +++ b/src/ndarray_linalg/tridiagonal.rs.html @@ -0,0 +1,1416 @@ +tridiagonal.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+
//! Vectors as a Tridiagonal matrix
+//! &
+//! Methods for tridiagonal matrices
+
+use super::convert::*;
+use super::error::*;
+use super::layout::*;
+use cauchy::Scalar;
+use lax::*;
+use ndarray::*;
+use num_traits::One;
+
+pub use lax::{LUFactorizedTridiagonal, Tridiagonal};
+
+/// An interface for making a Tridiagonal struct.
+pub trait ExtractTridiagonal<A: Scalar> {
+    /// Extract tridiagonal elements and layout of the raw matrix.
+    ///
+    /// If the raw matrix has some non-tridiagonal elements,
+    /// they will be ignored.
+    ///
+    /// The shape of raw matrix should be equal to or larger than (2, 2).
+    fn extract_tridiagonal(&self) -> Result<Tridiagonal<A>>;
+}
+
+impl<A, S> ExtractTridiagonal<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn extract_tridiagonal(&self) -> Result<Tridiagonal<A>> {
+        let l = self.square_layout()?;
+        let (n, _) = l.size();
+        if n < 2 {
+            return Err(LinalgError::NotStandardShape {
+                obj: "Tridiagonal",
+                rows: 1,
+                cols: 1,
+            });
+        }
+
+        let dl = self.slice(s![1..n, 0..n - 1]).diag().to_vec();
+        let d = self.diag().to_vec();
+        let du = self.slice(s![0..n - 1, 1..n]).diag().to_vec();
+        Ok(Tridiagonal { l, dl, d, du })
+    }
+}
+
+pub trait SolveTridiagonal<A: Scalar, D: Dimension> {
+    /// Solves a system of linear equations `A * x = b` with tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result.
+    fn solve_tridiagonal<S: Data<Elem = A>>(&self, b: &ArrayBase<S, D>) -> Result<Array<A, D>>;
+    /// Solves a system of linear equations `A * x = b` with tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result.
+    fn solve_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<S, D>,
+    ) -> Result<ArrayBase<S, D>>;
+    /// Solves a system of linear equations `A^T * x = b` with tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result.
+    fn solve_t_tridiagonal<S: Data<Elem = A>>(&self, b: &ArrayBase<S, D>) -> Result<Array<A, D>>;
+    /// Solves a system of linear equations `A^T * x = b` with tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result.
+    fn solve_t_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<S, D>,
+    ) -> Result<ArrayBase<S, D>>;
+    /// Solves a system of linear equations `A^H * x = b` with tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result.
+    fn solve_h_tridiagonal<S: Data<Elem = A>>(&self, b: &ArrayBase<S, D>) -> Result<Array<A, D>>;
+    /// Solves a system of linear equations `A^H * x = b` with tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result.
+    fn solve_h_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<S, D>,
+    ) -> Result<ArrayBase<S, D>>;
+}
+
+pub trait SolveTridiagonalInplace<A: Scalar, D: Dimension> {
+    /// Solves a system of linear equations `A * x = b` tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result. The value of `x` is also assigned to the
+    /// argument.
+    fn solve_tridiagonal_inplace<'a, S: DataMut<Elem = A>>(
+        &self,
+        b: &'a mut ArrayBase<S, D>,
+    ) -> Result<&'a mut ArrayBase<S, D>>;
+    /// Solves a system of linear equations `A^T * x = b` tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result. The value of `x` is also assigned to the
+    /// argument.
+    fn solve_t_tridiagonal_inplace<'a, S: DataMut<Elem = A>>(
+        &self,
+        b: &'a mut ArrayBase<S, D>,
+    ) -> Result<&'a mut ArrayBase<S, D>>;
+    /// Solves a system of linear equations `A^H * x = b` tridiagonal
+    /// matrix `A`, where `A` is `self`, `b` is the argument, and
+    /// `x` is the successful result. The value of `x` is also assigned to the
+    /// argument.
+    fn solve_h_tridiagonal_inplace<'a, S: DataMut<Elem = A>>(
+        &self,
+        b: &'a mut ArrayBase<S, D>,
+    ) -> Result<&'a mut ArrayBase<S, D>>;
+}
+
+impl<A> SolveTridiagonal<A, Ix2> for LUFactorizedTridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn solve_tridiagonal<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix2>) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<S, Ix2>,
+    ) -> Result<ArrayBase<S, Ix2>> {
+        self.solve_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_t_tridiagonal<S: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<S, Ix2>,
+    ) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_t_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_t_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<S, Ix2>,
+    ) -> Result<ArrayBase<S, Ix2>> {
+        self.solve_t_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_h_tridiagonal<S: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<S, Ix2>,
+    ) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_h_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_h_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<S, Ix2>,
+    ) -> Result<ArrayBase<S, Ix2>> {
+        self.solve_h_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+}
+
+impl<A> SolveTridiagonal<A, Ix2> for Tridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn solve_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix2>,
+    ) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<Sb, Ix2>,
+    ) -> Result<ArrayBase<Sb, Ix2>> {
+        self.solve_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_t_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix2>,
+    ) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_t_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_t_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<Sb, Ix2>,
+    ) -> Result<ArrayBase<Sb, Ix2>> {
+        self.solve_t_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_h_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix2>,
+    ) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_h_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_h_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<Sb, Ix2>,
+    ) -> Result<ArrayBase<Sb, Ix2>> {
+        self.solve_h_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+}
+
+impl<A, S> SolveTridiagonal<A, Ix2> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn solve_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix2>,
+    ) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<Sb, Ix2>,
+    ) -> Result<ArrayBase<Sb, Ix2>> {
+        self.solve_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_t_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix2>,
+    ) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_t_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_t_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<Sb, Ix2>,
+    ) -> Result<ArrayBase<Sb, Ix2>> {
+        self.solve_t_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_h_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix2>,
+    ) -> Result<Array<A, Ix2>> {
+        let mut b = replicate(b);
+        self.solve_h_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+    fn solve_h_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        mut b: ArrayBase<Sb, Ix2>,
+    ) -> Result<ArrayBase<Sb, Ix2>> {
+        self.solve_h_tridiagonal_inplace(&mut b)?;
+        Ok(b)
+    }
+}
+
+impl<A> SolveTridiagonalInplace<A, Ix2> for LUFactorizedTridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn solve_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        A::solve_tridiagonal(
+            self,
+            rhs.layout()?,
+            Transpose::No,
+            rhs.as_slice_mut().unwrap(),
+        )?;
+        Ok(rhs)
+    }
+    fn solve_t_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        A::solve_tridiagonal(
+            self,
+            rhs.layout()?,
+            Transpose::Transpose,
+            rhs.as_slice_mut().unwrap(),
+        )?;
+        Ok(rhs)
+    }
+    fn solve_h_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        A::solve_tridiagonal(
+            self,
+            rhs.layout()?,
+            Transpose::Hermite,
+            rhs.as_slice_mut().unwrap(),
+        )?;
+        Ok(rhs)
+    }
+}
+
+impl<A> SolveTridiagonalInplace<A, Ix2> for Tridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn solve_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize_tridiagonal()?;
+        f.solve_tridiagonal_inplace(rhs)
+    }
+    fn solve_t_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize_tridiagonal()?;
+        f.solve_t_tridiagonal_inplace(rhs)
+    }
+    fn solve_h_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize_tridiagonal()?;
+        f.solve_h_tridiagonal_inplace(rhs)
+    }
+}
+
+impl<A, S> SolveTridiagonalInplace<A, Ix2> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn solve_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize_tridiagonal()?;
+        f.solve_tridiagonal_inplace(rhs)
+    }
+    fn solve_t_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize_tridiagonal()?;
+        f.solve_t_tridiagonal_inplace(rhs)
+    }
+    fn solve_h_tridiagonal_inplace<'a, Sb>(
+        &self,
+        rhs: &'a mut ArrayBase<Sb, Ix2>,
+    ) -> Result<&'a mut ArrayBase<Sb, Ix2>>
+    where
+        Sb: DataMut<Elem = A>,
+    {
+        let f = self.factorize_tridiagonal()?;
+        f.solve_h_tridiagonal_inplace(rhs)
+    }
+}
+
+impl<A> SolveTridiagonal<A, Ix1> for LUFactorizedTridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn solve_tridiagonal<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_tridiagonal_into(b)
+    }
+    fn solve_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<S, Ix1>,
+    ) -> Result<ArrayBase<S, Ix1>> {
+        let b = into_col(b);
+        let b = self.solve_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+    fn solve_t_tridiagonal<S: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<S, Ix1>,
+    ) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_t_tridiagonal_into(b)
+    }
+    fn solve_t_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<S, Ix1>,
+    ) -> Result<ArrayBase<S, Ix1>> {
+        let b = into_col(b);
+        let b = self.solve_t_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+    fn solve_h_tridiagonal<S: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<S, Ix1>,
+    ) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_h_tridiagonal_into(b)
+    }
+    fn solve_h_tridiagonal_into<S: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<S, Ix1>,
+    ) -> Result<ArrayBase<S, Ix1>> {
+        let b = into_col(b);
+        let b = self.solve_h_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+}
+
+impl<A> SolveTridiagonal<A, Ix1> for Tridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn solve_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix1>,
+    ) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_tridiagonal_into(b)
+    }
+    fn solve_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<Sb, Ix1>,
+    ) -> Result<ArrayBase<Sb, Ix1>> {
+        let b = into_col(b);
+        let f = self.factorize_tridiagonal()?;
+        let b = f.solve_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+    fn solve_t_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix1>,
+    ) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_t_tridiagonal_into(b)
+    }
+    fn solve_t_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<Sb, Ix1>,
+    ) -> Result<ArrayBase<Sb, Ix1>> {
+        let b = into_col(b);
+        let f = self.factorize_tridiagonal()?;
+        let b = f.solve_t_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+    fn solve_h_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix1>,
+    ) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_h_tridiagonal_into(b)
+    }
+    fn solve_h_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<Sb, Ix1>,
+    ) -> Result<ArrayBase<Sb, Ix1>> {
+        let b = into_col(b);
+        let f = self.factorize_tridiagonal()?;
+        let b = f.solve_h_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+}
+
+impl<A, S> SolveTridiagonal<A, Ix1> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn solve_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix1>,
+    ) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_tridiagonal_into(b)
+    }
+    fn solve_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<Sb, Ix1>,
+    ) -> Result<ArrayBase<Sb, Ix1>> {
+        let b = into_col(b);
+        let f = self.factorize_tridiagonal()?;
+        let b = f.solve_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+    fn solve_t_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix1>,
+    ) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_t_tridiagonal_into(b)
+    }
+    fn solve_t_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<Sb, Ix1>,
+    ) -> Result<ArrayBase<Sb, Ix1>> {
+        let b = into_col(b);
+        let f = self.factorize_tridiagonal()?;
+        let b = f.solve_t_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+    fn solve_h_tridiagonal<Sb: Data<Elem = A>>(
+        &self,
+        b: &ArrayBase<Sb, Ix1>,
+    ) -> Result<Array<A, Ix1>> {
+        let b = b.to_owned();
+        self.solve_h_tridiagonal_into(b)
+    }
+    fn solve_h_tridiagonal_into<Sb: DataMut<Elem = A>>(
+        &self,
+        b: ArrayBase<Sb, Ix1>,
+    ) -> Result<ArrayBase<Sb, Ix1>> {
+        let b = into_col(b);
+        let f = self.factorize_tridiagonal()?;
+        let b = f.solve_h_tridiagonal_into(b)?;
+        Ok(flatten(b))
+    }
+}
+
+/// An interface for computing LU factorizations of tridiagonal matrix refs.
+pub trait FactorizeTridiagonal<A: Scalar> {
+    /// Computes the LU factorization `A = P*L*U`, where `P` is a permutation
+    /// matrix.
+    fn factorize_tridiagonal(&self) -> Result<LUFactorizedTridiagonal<A>>;
+}
+
+/// An interface for computing LU factorizations of tridiagonal matrices.
+pub trait FactorizeTridiagonalInto<A: Scalar> {
+    /// Computes the LU factorization `A = P*L*U`, where `P` is a permutation
+    /// matrix.
+    fn factorize_tridiagonal_into(self) -> Result<LUFactorizedTridiagonal<A>>;
+}
+
+impl<A> FactorizeTridiagonalInto<A> for Tridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn factorize_tridiagonal_into(self) -> Result<LUFactorizedTridiagonal<A>> {
+        Ok(A::lu_tridiagonal(self)?)
+    }
+}
+
+impl<A> FactorizeTridiagonal<A> for Tridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn factorize_tridiagonal(&self) -> Result<LUFactorizedTridiagonal<A>> {
+        let a = self.clone();
+        Ok(A::lu_tridiagonal(a)?)
+    }
+}
+
+impl<A, S> FactorizeTridiagonal<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn factorize_tridiagonal(&self) -> Result<LUFactorizedTridiagonal<A>> {
+        let a = self.extract_tridiagonal()?;
+        Ok(A::lu_tridiagonal(a)?)
+    }
+}
+
+/// Calculates the recurrent relation,
+/// f_k = a_k * f_{k-1} - c_{k-1} * b_{k-1} * f_{k-2}
+/// where {a_1, a_2, ..., a_n} are diagonal elements,
+/// {b_1, b_2, ..., b_{n-1}} are super-diagonal elements, and
+/// {c_1, c_2, ..., c_{n-1}} are sub-diagonal elements of matrix.
+///
+/// f[n] is used to calculate the determinant.
+/// (https://en.wikipedia.org/wiki/Tridiagonal_matrix#Determinant)
+///
+/// In the future, the vector `f` can be used to calculate the inverce matrix.
+/// (https://en.wikipedia.org/wiki/Tridiagonal_matrix#Inversion)
+fn rec_rel<A: Scalar>(tridiag: &Tridiagonal<A>) -> Vec<A> {
+    let n = tridiag.d.len();
+    let mut f = Vec::with_capacity(n + 1);
+    f.push(One::one());
+    f.push(tridiag.d[0]);
+    for i in 1..n {
+        f.push(tridiag.d[i] * f[i] - tridiag.dl[i - 1] * tridiag.du[i - 1] * f[i - 1]);
+    }
+    f
+}
+
+/// An interface for calculating determinants of tridiagonal matrix refs.
+pub trait DeterminantTridiagonal<A: Scalar> {
+    /// Computes the determinant of the matrix.
+    /// Unlike `.det()` of Determinant trait, this method
+    /// doesn't returns the natural logarithm of the determinant
+    /// but the determinant itself.
+    fn det_tridiagonal(&self) -> Result<A>;
+}
+
+impl<A> DeterminantTridiagonal<A> for Tridiagonal<A>
+where
+    A: Scalar,
+{
+    fn det_tridiagonal(&self) -> Result<A> {
+        let n = self.d.len();
+        Ok(rec_rel(self)[n])
+    }
+}
+
+impl<A, S> DeterminantTridiagonal<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn det_tridiagonal(&self) -> Result<A> {
+        let tridiag = self.extract_tridiagonal()?;
+        let n = tridiag.d.len();
+        Ok(rec_rel(&tridiag)[n])
+    }
+}
+
+/// An interface for *estimating* the reciprocal condition number of tridiagonal matrix refs.
+pub trait ReciprocalConditionNumTridiagonal<A: Scalar> {
+    /// *Estimates* the reciprocal of the condition number of the tridiagonal matrix in
+    /// 1-norm.
+    ///
+    /// This method uses the LAPACK `*gtcon` routines, which *estimate*
+    /// `self.inv_tridiagonal().opnorm_one()` and then compute `rcond = 1. /
+    /// (self.opnorm_one() * self.inv_tridiagonal().opnorm_one())`.
+    ///
+    /// * If `rcond` is near `0.`, the matrix is badly conditioned.
+    /// * If `rcond` is near `1.`, the matrix is well conditioned.
+    fn rcond_tridiagonal(&self) -> Result<A::Real>;
+}
+
+/// An interface for *estimating* the reciprocal condition number of tridiagonal matrices.
+pub trait ReciprocalConditionNumTridiagonalInto<A: Scalar> {
+    /// *Estimates* the reciprocal of the condition number of the tridiagonal matrix in
+    /// 1-norm.
+    ///
+    /// This method uses the LAPACK `*gtcon` routines, which *estimate*
+    /// `self.inv_tridiagonal().opnorm_one()` and then compute `rcond = 1. /
+    /// (self.opnorm_one() * self.inv_tridiagonal().opnorm_one())`.
+    ///
+    /// * If `rcond` is near `0.`, the matrix is badly conditioned.
+    /// * If `rcond` is near `1.`, the matrix is well conditioned.
+    fn rcond_tridiagonal_into(self) -> Result<A::Real>;
+}
+
+impl<A> ReciprocalConditionNumTridiagonal<A> for LUFactorizedTridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn rcond_tridiagonal(&self) -> Result<A::Real> {
+        Ok(A::rcond_tridiagonal(self)?)
+    }
+}
+
+impl<A> ReciprocalConditionNumTridiagonalInto<A> for LUFactorizedTridiagonal<A>
+where
+    A: Scalar + Lapack,
+{
+    fn rcond_tridiagonal_into(self) -> Result<A::Real> {
+        self.rcond_tridiagonal()
+    }
+}
+
+impl<A, S> ReciprocalConditionNumTridiagonal<A> for ArrayBase<S, Ix2>
+where
+    A: Scalar + Lapack,
+    S: Data<Elem = A>,
+{
+    fn rcond_tridiagonal(&self) -> Result<A::Real> {
+        self.factorize_tridiagonal()?.rcond_tridiagonal_into()
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/ndarray_linalg/types.rs.html b/src/ndarray_linalg/types.rs.html new file mode 100644 index 00000000..8f9e28a6 --- /dev/null +++ b/src/ndarray_linalg/types.rs.html @@ -0,0 +1,40 @@ +types.rs - source + + + + + + +
1
+2
+3
+4
+5
+6
+7
+
//! Basic types and their methods for linear algebra
+
+pub use cauchy::Scalar;
+pub use lax::Lapack;
+
+pub use num_complex::Complex32 as c32;
+pub use num_complex::Complex64 as c64;
+
+
+ \ No newline at end of file diff --git a/storage.js b/storage.js new file mode 100644 index 00000000..ad14b2a0 --- /dev/null +++ b/storage.js @@ -0,0 +1 @@ +"use strict";const darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");window.mainTheme=document.getElementById("mainThemeStyle");const settingsDataset=(function(){const settingsElement=document.getElementById("default-settings");if(settingsElement===null){return null}const dataset=settingsElement.dataset;if(dataset===undefined){return null}return dataset})();function getSettingValue(settingName){const current=getCurrentValue(settingName);if(current!==null){return current}if(settingsDataset!==null){const def=settingsDataset[settingName.replace(/-/g,"_")];if(def!==undefined){return def}}return null}const localStoredTheme=getSettingValue("theme");const savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){if(reversed){const length=arr.length;for(let i=length-1;i>=0;--i){if(func(arr[i])){return true}}}else{for(const elem of arr){if(func(elem)){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function updateLocalStorage(name,value){try{window.localStorage.setItem("rustdoc-"+name,value)}catch(e){}}function getCurrentValue(name){try{return window.localStorage.getItem("rustdoc-"+name)}catch(e){return null}}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){const newHref=mainStyleElem.href.replace(/\/rustdoc([^/]*)\.css/,"/"+newTheme+"$1"+".css");if(saveTheme){updateLocalStorage("theme",newTheme)}if(styleElem.href===newHref){return}let found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),el=>{savedHref.push(el.href)})}onEach(savedHref,el=>{if(el===newHref){found=true;return true}});if(found){styleElem.href=newHref}}function useSystemTheme(value){if(value===undefined){value=true}updateLocalStorage("use-system-theme",value);const toggle=document.getElementById("use-system-theme");if(toggle&&toggle instanceof HTMLInputElement){toggle.checked=value}}const updateSystemTheme=(function(){if(!window.matchMedia){return()=>{const cssTheme=getComputedStyle(document.documentElement).getPropertyValue("content");switchTheme(window.currentTheme,window.mainTheme,JSON.parse(cssTheme)||"light",true)}}const mql=window.matchMedia("(prefers-color-scheme: dark)");function handlePreferenceChange(mql){const use=theme=>{switchTheme(window.currentTheme,window.mainTheme,theme,true)};if(getSettingValue("use-system-theme")!=="false"){const lightTheme=getSettingValue("preferred-light-theme")||"light";const darkTheme=getSettingValue("preferred-dark-theme")||"dark";if(mql.matches){use(darkTheme)}else{use(lightTheme)}}else{use(getSettingValue("theme"))}}mql.addListener(handlePreferenceChange);return()=>{handlePreferenceChange(mql)}})();function switchToSavedTheme(){switchTheme(window.currentTheme,window.mainTheme,getSettingValue("theme")||"light",false)}if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("preferred-dark-theme",localStoredTheme)}updateSystemTheme()}else{switchToSavedTheme()}if(getSettingValue("source-sidebar-show")==="true"){addClass(document.documentElement,"source-sidebar-expanded")}window.addEventListener("pageshow",ev=>{if(ev.persisted){setTimeout(switchToSavedTheme,0)}}) \ No newline at end of file diff --git a/toggle-minus.svg b/toggle-minus.svg new file mode 100644 index 00000000..73154788 --- /dev/null +++ b/toggle-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/toggle-plus.svg b/toggle-plus.svg new file mode 100644 index 00000000..08b17033 --- /dev/null +++ b/toggle-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wheel.svg b/wheel.svg new file mode 100644 index 00000000..01da3b24 --- /dev/null +++ b/wheel.svg @@ -0,0 +1 @@ + \ No newline at end of file