pax_global_header00006660000000000000000000000064126332076400014515gustar00rootroot0000000000000052 comment=e77dca708b386000562ec0c0def44a59d61add3d la4j-0.6.0/000077500000000000000000000000001263320764000123525ustar00rootroot00000000000000la4j-0.6.0/.gitignore000066400000000000000000000001111263320764000143330ustar00rootroot00000000000000*.class *.iml *.classpath *.project .settings /target/ /.idea/ Demo.java la4j-0.6.0/.travis.yml000066400000000000000000000001121263320764000144550ustar00rootroot00000000000000sudo: false language: java jdk: - oraclejdk7 - oraclejdk8 - openjdk7la4j-0.6.0/CHANGELOG.md000066400000000000000000000205341263320764000141670ustar00rootroot00000000000000Changelog --------- la4j-0.6.0 `Dec 2015` * Fix validation errors in `Matrix.insert` * New matrix methods `insertRow` and `insertColumn` * Support comments in Matrix Market format * New `NO_PIVOT_GAUSS` matrix inverter * New matrix norms: Euclidean, Infinity and Manhattan * New factory methods for `Vector`: `fromMap` and `fromCollection` la4j-0.5.5 `Jan 2015` * Removed deprecated package `org.la4j.factory` * Bug fix in sparse matrix iterators * Improved performance of vector by value multiplication * Removed deprecated package `org.la4j.io` * New static factory methods `Vector.*` and `Matrix.*` la4j-0.5.0 `Jan 2015` * Matrix and vector iterators in package `org.la4j.iterator` * Matrix and vector operations in package `org.la4j.operations` * Replaced factories with static factory methods * Bug fix in serialization algorithm of sparse matrices (contributed by Catherine da Graca)` * New sparse matrix methods: `foldNonZero()`, `foldNonZeroInRow()`, `foldNonZeroInColumn()`, `foldNonZeroInColumns()`, `foldNonZeroInRows()` * New sparse vector method: `foldNonZero()` * New matrix/vector method `mkString()` for customized to-string conversion * Bug fix in random generation of sparse matrices * New sparse methods: `isZeroAt()` and `nonZeroAt()` * Method `eachNonZero` is available only for sparse entities * New sparse method: `getOrElse()` * Bug fix in `resize()` method of sparse vector (reported by Leonid Ilyevsky) * New matrix methods: `removeRow()`, `removeColumn()` (contributed by Maxim Samoylov) * Tests migrated to latest junit version, removed `MockVector` and `MockMatrix` classes (contributed by Maxim Samoylov) * New vector method `equals(vector, precision)` * New matrix method `equals(matrix, precision)` * New vector methods `norm`, `euclideanNorm`, `manhattanNorm` and `infinityNorm` * Added index range checks for `SparseVector` * Added index range checks for `Basic1DMatrix`, `CRSMatrix`, and `CCSMatrix` la4j-0.4.9 `Jan 2014` * Bug fix in `align()` method for big sparse matrices (reported by Michael Kapper) * Bug fix in `growup()` method for big sparse matrices (contributed by Phil Messenger) * Bug fix in `MatrixMarketStream` * New matrix method `select()` (contributed by Anveshi Charuvaka) * New vector method `select()` * Bug fix in `growup()` method for the case with positive overflow (contributed by Clement Skau) * New matrix predicate `Matrices.SQUARE_MATRIX` (contributed by Miron Aseev) * New matrix predicate `Matrices.INVERTIBLE_MATRIX` (contributed by Miron Aseev) * New vector method `norm(NormFunction)` that implements p-norm support (contributed by Miron Aseev) * New matrix predicate `PositiveDefiniteMatrix` (contributed by Miron Aseev) * Bug fix in `each`, `eachInRow`, `eachInColumn` methods of sparse matrices (reported by Leonid Ilyevsky) * New matrix methods: `foldColumns` and `foldRows` (contributed by Todd Brunhoff) * New matrix methods: `assignRow` and `assignColumn` * New matrix methods: `updateRow` and `updateColumn` * New matrix methods: `transformRow` and `transformColumn` la4j-0.4.5 `Sep 2013` * New vector methods: `innerProduct()`, `outerProduct()` (contributed by Daniel Renshaw) * Bug fix in `Vector.subtract()` method (contributed by Ewald Grusk) * Bug fix in `Matrix.subtract()` method (contributed by Ewald Grusk) * New matrix method `rotate()` (contributed by Jakob Moellers) * New matrix method `shuffle()` (contributed by Jakob Moellers) * Bug fix in `Vector.density()` and `Matrix.density()` (contributed by Ewald Grusk) * Bug fix in `Matrix.determinant()` method (contributed by Yuriy Drozd) * Minor improvement of `SymmetricMatrixPredicate` (contributed by Ewald Grusk) * Bug fix in `EigenDecompositor` (reported by Ewald Grusk) * Bug fix in `CompressedVector.swap()` (reported by Ewald Grusk, contributed by Yuriy Drozd) * Typo fix in `IdentityMattixSource` (reported by Ewald Grusk, contributed by Yuriy Drozd) * Renamed `Matrix.product()` to `Matrix.diagonalProduct()` (contributed by Julia Kostyukova) * New matrix methods: `sum()` and `product()` (contributed by Julia Kostyukova) * New vector methods: `sum()` and `product()` (contributed by Julia Kostyukova) * Renamed `Matrix.kronecker()` to `Matrix.kroneckerProduct()` (contributed by Julia Kostyukova) * New matrix method `hadamardProduct()` (contributed by Julia Kostyukova) * Bug fix in `EigenDecompositor` (contributed by Maxim Samoylov) * Improved stability of `EigenDecompositor` (contributed by Maxim Samoylov) * New vector method `eachNonZero` (contributed by Maxim Samoylov) * New matrix method `power` (contributed by Jakob Moellers) * New matrix methods `eachInRow`, `eachInColumn`(contributed by Maxim Samoylov) * New matrix methods `eachNonZeroInRow`, `eachNonZeroInColumn`, `eachNonZero` (contributed by Maxim Samoylov) * New factory method `createBlockMatrix` (contributed by Maxim Samoylov) * New fast and stable algorithm for determinant calculation (contributed by Maxim Samoylov) * Improved stability of accumulators (contributed by Maxim Samoylov) * Bug fix in `Matrix.rank()` method (contributed by Ewald Grusk) * Bug fix in `SingularValueDecompositor` class (reported by Jonathan Edwards) * Fixed a typo in `MatrixInvertor` -> `MatrixInverter` * New function `Mod` (requested by Luc Trudeau) * Bug fix in `GaussianSolver` * Bug fix in `SquareRootSolver` * Bug fix in `JacobiSolver` * New matrix and vector methods `max()`, `min()`, `minInRow()`, `maxInColumn()` (contributed by Maxim Samoylov) * New linear solver: `ForwardBackSubstitutionSolver` (for square systems) * New linear solver: `LeastSquaresSolver` (least squares solver) * New all-things-in-one class `LinearAlgebra` * New matrix/vector method: `non()`, which is actually `!is()` delegate * New matrix to vector converters: `toRowVector()`, `toColumnVector()` * New vector to matrix converters: `toRowMatrix()`, `toColumnMatrix()` * New API for solving system of linear equations: `withSolver(SolverFactory)` * New API for decomposing: `withDecompositor(DecompositorFactory)` * New API for inverting: `withInverter(InverterFactory)` la4j-0.4.0 `Jun 2013` * Up to 2x performance improvement of sparse entries (binary search power) * Performance improvement for matrix-by-matrix multiply algorithm (3x for dense, 11x for sparse) * New matrix method `rank()` (contributed by Evgenia Krivova) * New fast implementation of `Matrix.determinant()` method * New method `update()` (as compound operator replacement) * Matrices are unsafe by default (new corresponding methods `safe()` and `unsafe()`) * New method `slice()` * New matrix method `kronecker()` (contributed by Stefano Iannello) * Support map-reduce approach by method pair `transform()` and `fold()` * New matrices and vectors sources that handles IO streams * Support of building a constant matrix in factories (via `createConstantMatrix()`) * Matrices and vectors are immutable in terms of dimension * Sparse entities are self-clearing (no memory leaks) * Support vector-by-matrix multiplication * Bug fix in `MatrixDecFunction` * Bug fix in `MatrixMarketStream` (contributed by Alessio Placitelli) * Bug fix in matrix-to-vector multiplication (contributed by Pavel Kalaidin) * Bug fix in `align()` method (contributed by Chandler May) * Bug fix in `QRDecompositor` la4j-0.3.0 `Dec 2012` * New API and new package naming (starting with "org.la4j.*") * New source code hosting system - GitHub * New matrix types Basic1DMatrix and CCSMatrix * New I/O API and format - Symbol Separated Stream (CSV, TSV, etc.); * New entries: matrix/vector sources, matrix/vector functors * New exception model * Support of unsafe accessors and arithmetics methods * Support Eigenvalues decomposition for non-symmetric matrix * New fast matrix-to-matrix multiply algorithm with blocks * New algorithm for runtime-based machine epsilon initialization * Bug fixes for several major/critical issues la4j-0.2.0 `Nov 2011` * New package la4j.io for reading/writing matrices in MatrixMarket format * New matrices decomposition (LU, QR, Cholesky, SVD, Eigenvalues) * New sparse (Compressed Row Storage), dense matrices and vectors support * Matrices and vectors can be serialized la4j-0.1.0 `Jan 2011` * Eigenvalues decomposition * Fast matrix multiply algorithm implementation la4j-0.0.7 `Mar 2010` * Solving linear systems * Matrices transposing * Calculation of inverted matrix la4j 0.0.0 `Jan 2010` * Support real matrices and vectors la4j-0.6.0/CONTRIBUTORS.md000066400000000000000000000006641263320764000146370ustar00rootroot00000000000000Contributors ------------ The [**la4j**](http://la4j.org) wouldn't be the library it is today without the source contributions made by the authors: - Wajdy Essam - Evgenia Krivova - Julia Kostyukova - Alessio Placitelli - Pavel Kalaidin - Chandler May - Daniel Renshaw - Ewald Grusk - Jakob Moellers - Iurii Drozd - Maxim Samoylov - Phil Messenger - Anveshi Charuvaka - Clement Skau - Miron Aseev - Todd Brunhoff - Catherine da Graca la4j-0.6.0/LICENSE000066400000000000000000000261351263320764000133660ustar00rootroot00000000000000 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.la4j-0.6.0/README.md000066400000000000000000000030641263320764000136340ustar00rootroot00000000000000

[![Build Status](https://travis-ci.org/vkostyukov/la4j.svg?branch=master)](https://travis-ci.org/vkostyukov/la4j) [la4j](http://la4j.org) (Linear Algebra for Java) is an open source and **100% Java** library that provides _Linear Algebra_ primitives (matrices and vectors) and algorithms. The la4j library was initially designed to be a lightweight and simple tool for passionate Java developers. It has been started as student project and turned into one of the most popular Java packages for matrices and vectors. Instalation ----------- ```xml org.la4j la4j 0.6.0 ``` Changelog ------------ See [CHANGELOG.md](https://github.com/vkostyukov/la4j/blob/master/CHANGELOG.md) Contributors ------------ See [CONTRIBUTORS.md](https://github.com/vkostyukov/la4j/blob/master/CONTRIBUTORS.md) License ------- Licensed under the **[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)** (the "License"); you may not use this software except in compliance with the License. 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. ---- by [Vladimir Kostyukov](https://twitter.com/vkostyukov), 2011-2015 la4j-0.6.0/la4j-logo.png000066400000000000000000000164571263320764000146650ustar00rootroot00000000000000PNG  IHDROb< pHYs.#.#x?v cHRMz%u0`:o_FIDATx_lV+p7p--@7M"a*FQ 䢐Irl/F ıӕVJiuwH]LsjMZ0+dqز.Lւ^ؐ~y?J>|{~=g͛7@<' x @<' ē-O @<' lxO @<'d xO @<'[ xO @< xO' xO@<' iq>̚=oDrXԿw4S>Dģ+j (ev @<' O @<' O @<'2gPۂTb^u \KM-@3pʔp?t#ї1x "❞֦J0#Q8ͷetum1WMTx ^imKj2v8.p8}5?A<6}`8Uqt©c7ק<GP9"HlM;67ԋ'.G/ڑp '2-q]mD3- )/sx R5ܼ>lˣ @iIy\3mYF@ēx`P^oQ'S*d,}OkӮDX}+He\x E?im:`8Նq $9[h!zy-'""q]ZO%.q]}ڬ:g 3uC+Ryx{N<׍JD6[<GGOkSsT㺹v:SHa\7ײx'E͏RݝN :zZ~`8¸n>><u@G[D\Hty'Xp6Fyպ3㯌?Ėu$kϢO-"9D 9ҹy|쪓xȮW}Y8:"bcD\]\O,t4M0 a\J@EDՈˣ @1\@[u8'yq0E%P1@{8'X KD%6MwK BץP}:jcV)SDb̎bEyT_vUoGDc';ވKqw0ވ. Gp ^ɥ͸F΁ m1'gW=@<,+_$jG]x|Jt7-]|w;/DץzoG%#q0R@ 1"E8G'Uش*[W eImU,6VŦڪ6z#:>7Q,-=w%{OC:2" 2[Wu*O[vH]}ǾʇTu;cvYܺؾamrWbU,~7bh;'+q]Ãxєh}K kcMu =u5+gU4-8x߁φu&ɤ$U[: coxo[]O=j~:ioq7ɳGDDЈ͘[u @8)siԸ 'jSmMniܕO'He\ )iwKé6] N8 '2ƸnzvFD3^U2A֤:69uO06=,Ju\W;ݳթxض7Ȣ$uw-D㺭=MCNLS<^yh#Ȣ퉮9"HtmGzZ;uO0Mn zݸn.q fMA,nilN0 a\j(\i#Ț?G/mtuo6w `ʗ.7c2ƞq]S3jcу0ɢƟ%N0O$VW"%4]O#ui8Go?_U(U,q>yݸ3cRGSwNuˣRL'qHw\w٩xxn]U'Ue BD7-"ja<^{f\xِN}m'bxz2kQ ŕ泏3ѩCxTUC#۟ľc_$NOϏo?;uA< m]_u۟Dץ:`}WwuӳѸ|xnw싒6ڮCtw`\7eo6w `xK~KM~Iz Hw\w!ᵁx"T"5Ӓ=Oz!÷O0'ؕ}WwnK-ImQu (AK$w_zE-5{ګ#ݑ֦ŃbeZӗPi0N̑Fv«[5G{Zx9PBWObfm\7T%g{ZA<ZU( ;T{.E"xFJ)ItϚOPBtmgMr}䷌DOk^ZO0˖_r@&YZ,-;][[2C<|Ivi4ޔԣ)>ROPb>0y`O[$Nq QJ)pS[w%De\xV4{D\FKOPlG~Ҹqim:O c0;Kr\zBD'u'[@6z&~퉮9"Htmu'[@W#bG{q'`rxc?'NHub'[\SsׁxHпv4&wڀxb򌧈H$p*Da\ *zA1Oa\ %_}Gkimsƃx"QFo$U2,>kT:O0]\Z;L?tw Tu"OwuOΓw9߱˕'6aU2MD :$JdtC=x" dR(wӄx" C#Iէ HFwϭr@!(D:=V<x@X'էJ^O+O ȻGen[Wljn.XD5W/<m=YYgc{}K kcq\<{1:{YU(bEl]_tROmu]ڱw]ξWbxw]͊^ ŕ0';rԳHO `:{u뻶O'{й~t,[?@fO8 uS/k7do)}5{78x;?ϼ&pJw%~զo0ۭj>3uqh$[=n5{߰ ,0w0F]͊رamni% R}G\xz'i׈OwK ϋ1owԿ"OLo"bO~5">JLx`b"?Ě=7g}t?O}OkqXO̗EϻxOYq&뉈Xo6;'O l ջ>bO0yߵ'<;ē-@<Γ@<Uw}6 `'Ỏm &omA67' ĉ'ȗz[ ɫ 'd lne@x'`67TGZ҅}ވ8w[ӗ׍^tM@|"!"@GHSDđz{,v:x "lncW ؛`8EDO0EĎ1xH<1ܰ5"ǣ,E}y= #1t!Ʈ|H X|/'\^GB偎!090ێ'$Ywu]O@);(tX<LU0y|'̶!0N[v MͥA0SG*tOv5"vOL<'D偎R ?xN@LV8+ OpOpO8ib[LjD4Wk+̏#b[DzDDpE7o޴ YElBF ln(DD}='icD,Khy'bjd=xbcv<#XՈhyzՊx@<11U?R+S"pD?x@<11U!UBD<2Ո8C=7LC y@ m; xO' xO' xO' xO'07,06\IENDB`la4j-0.6.0/pom.xml000066400000000000000000000050321263320764000136670ustar00rootroot00000000000000 4.0.0 org.la4j la4j jar 0.6.0 la4j http://la4j.org A 100% Java sparse and dense matrix library. The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo vkostyukov Vladimir Kostyukov vladimir.v.kostyukov@gmail.com junit junit 4.11 test org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.7 1.7 true true org.apache.maven.plugins maven-javadoc-plugin 2.10.1 attach-javadocs jar org.sonatype.oss oss-parent 7 ossrh https://oss.sonatype.org/content/repositories/snapshots ossrh https://oss.sonatype.org/service/local/staging/deploy/maven2/ scm:git:git@github.com:vkostyukov/la4j.git scm:git:git@github.com:vkostyukov/la4j.git git@github.com:vkostyukov/la4j.git la4j-0.6.0/src/000077500000000000000000000000001263320764000131415ustar00rootroot00000000000000la4j-0.6.0/src/main/000077500000000000000000000000001263320764000140655ustar00rootroot00000000000000la4j-0.6.0/src/main/java/000077500000000000000000000000001263320764000150065ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/000077500000000000000000000000001263320764000155755ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/000077500000000000000000000000001263320764000164275ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/LinearAlgebra.java000066400000000000000000000303261263320764000217660ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - */ package org.la4j; import org.la4j.decomposition.CholeskyDecompositor; import org.la4j.decomposition.EigenDecompositor; import org.la4j.decomposition.LUDecompositor; import org.la4j.decomposition.MatrixDecompositor; import org.la4j.decomposition.QRDecompositor; import org.la4j.decomposition.RawLUDecompositor; import org.la4j.decomposition.RawQRDecompositor; import org.la4j.decomposition.SingularValueDecompositor; import org.la4j.inversion.NoPivotGaussInverter; import org.la4j.inversion.GaussJordanInverter; import org.la4j.inversion.MatrixInverter; import org.la4j.linear.ForwardBackSubstitutionSolver; import org.la4j.linear.GaussianSolver; import org.la4j.linear.JacobiSolver; import org.la4j.linear.LeastSquaresSolver; import org.la4j.linear.LinearSystemSolver; import org.la4j.linear.SeidelSolver; import org.la4j.linear.SquareRootSolver; import org.la4j.linear.SweepSolver; import org.la4j.operation.MatrixMatrixOperation; import org.la4j.operation.MatrixOperation; import org.la4j.operation.MatrixVectorOperation; import org.la4j.operation.inplace.InPlaceCopyMatrixToMatrix; import org.la4j.operation.ooplace.OoPlaceKroneckerProduct; import org.la4j.operation.ooplace.OoPlaceMatricesAddition; import org.la4j.operation.ooplace.OoPlaceMatricesMultiplication; import org.la4j.operation.ooplace.OoPlaceMatricesSubtraction; import org.la4j.operation.ooplace.OoPlaceMatrixByItsTransposeMultiplication; import org.la4j.operation.ooplace.OoPlaceMatrixByVectorMultiplication; import org.la4j.operation.ooplace.OoPlaceMatrixHadamardProduct; import org.la4j.operation.VectorMatrixOperation; import org.la4j.operation.VectorVectorOperation; import org.la4j.operation.ooplace.OoPlaceVectorHadamardProduct; import org.la4j.operation.ooplace.OoPlaceInnerProduct; import org.la4j.operation.ooplace.OoPlaceOuterProduct; import org.la4j.operation.ooplace.OoPlaceVectorByMatrixMultiplication; import org.la4j.operation.ooplace.OoPlaceVectorsSubtraction; import org.la4j.operation.ooplace.OoPlaceVectorsAddition; /** * Tiny class for common things. */ public final class LinearAlgebra { /** * The library version. */ public static final String VERSION = "0.5.5"; /** * The library name. */ public static final String NAME = "la4j"; /** * The library release date. */ public static final String DATE = "March 2015"; /** * The library full name. */ public static final String FULL_NAME = NAME + "-" + VERSION + " (" + DATE + ")"; /** * The machine epsilon, which is calculated at runtime. */ public static final double EPS; /** * Exponent of machine epsilon */ public static final int ROUND_FACTOR; // Determine the machine epsilon // Tolerance is 10e1 static { int roundFactor = 0; double eps = 1.0; while (1 + eps > 1) { eps = eps / 2; roundFactor++; } EPS = eps * 10e1; ROUND_FACTOR = roundFactor - 1; } public static enum SolverFactory { GAUSSIAN { @Override public LinearSystemSolver create(Matrix matrix) { return new GaussianSolver(matrix); } }, JACOBI { @Override public LinearSystemSolver create(Matrix matrix) { return new JacobiSolver(matrix); } }, SEIDEL { @Override public LinearSystemSolver create(Matrix matrix) { return new SeidelSolver(matrix); } }, FORWARD_BACK_SUBSTITUTION { @Override public LinearSystemSolver create(Matrix matrix) { return new ForwardBackSubstitutionSolver(matrix); } }, LEAST_SQUARES { @Override public LinearSystemSolver create(Matrix matrix) { return new LeastSquaresSolver(matrix); } }, SQUARE_ROOT { @Override public LinearSystemSolver create(Matrix matrix) { return new SquareRootSolver(matrix); } }, SWEEP { @Override public LinearSystemSolver create(Matrix matrix) { return new SweepSolver(matrix); } }, SMART { @Override public LinearSystemSolver create(Matrix matrix) { // TODO: We can do it smarter in future if (matrix.rows() == matrix.columns()) { return new ForwardBackSubstitutionSolver(matrix); } else if (matrix.rows() > matrix.columns()) { return new LeastSquaresSolver(matrix); } throw new IllegalArgumentException("Underdetermined system of linear equations can not be solved."); } }; public abstract LinearSystemSolver create(Matrix matrix); } /** * References to the Gaussian solver factory. */ public static final SolverFactory GAUSSIAN = SolverFactory.GAUSSIAN; /** * References to the Jacobi solver factory. */ public static final SolverFactory JACOBI = SolverFactory.JACOBI; /** * References to the Seidel solver factory. */ public static final SolverFactory SEIDEL = SolverFactory.SEIDEL; /** * References to the Least Squares solver factory. */ public static final SolverFactory LEAST_SQUARES = SolverFactory.LEAST_SQUARES; /** * References to the Forward-Back Substitution solver factory. */ public static final SolverFactory FORWARD_BACK_SUBSTITUTION = SolverFactory.FORWARD_BACK_SUBSTITUTION; /** * References to the Square Root solver factory. */ public static final SolverFactory SQUARE_ROOT = SolverFactory.SQUARE_ROOT; /** * References to the Smart solver factory. */ public static final SolverFactory SOLVER = SolverFactory.SMART; /** * References to the Sweep solver factory. */ public static final SolverFactory SWEEP = SolverFactory.SWEEP; public static enum InverterFactory { GAUSS_JORDAN { @Override public MatrixInverter create(Matrix matrix) { return new GaussJordanInverter(matrix); } }, NO_PIVOT_GAUSS { @Override public MatrixInverter create(Matrix matrix) { return new NoPivotGaussInverter(matrix); } }, SMART { @Override public MatrixInverter create(Matrix matrix) { return new GaussJordanInverter(matrix); } }; public abstract MatrixInverter create(Matrix matrix); } /** * Reference to an inverter factory solving n linear systems. */ public static final InverterFactory GAUSS_JORDAN = InverterFactory.GAUSS_JORDAN; /** * Reference to the Gauss elimination method-based inverter factory. * * Note: this version of the Gauss elimination method does not use a * pivot and does not swap either columns or rows. As a result, it will fail * if there is a zero on the diagonal. */ public static final InverterFactory NO_PIVOT_GAUSS = InverterFactory.NO_PIVOT_GAUSS; /** * Reference to the Smart inverter factory. */ public static final InverterFactory INVERTER = InverterFactory.SMART; public static enum DecompositorFactory { CHOLESKY { @Override public MatrixDecompositor create(Matrix matrix) { return new CholeskyDecompositor(matrix); } }, EIGEN { @Override public MatrixDecompositor create(Matrix matrix) { return new EigenDecompositor(matrix); } }, RAW_LU { @Override public MatrixDecompositor create(Matrix matrix) { return new RawLUDecompositor(matrix); } }, LU { @Override public MatrixDecompositor create(Matrix matrix) { return new LUDecompositor(matrix); } }, RAW_QR { @Override public MatrixDecompositor create(Matrix matrix) { return new RawQRDecompositor(matrix); } }, QR { @Override public MatrixDecompositor create(Matrix matrix) { return new QRDecompositor(matrix); } }, SVD { @Override public MatrixDecompositor create(Matrix matrix) { return new SingularValueDecompositor(matrix); } }; public abstract MatrixDecompositor create(Matrix matrix); } /** * Reference to Cholesky decompositor factory. */ public static final DecompositorFactory CHOLESKY = DecompositorFactory.CHOLESKY; /** * Reference to Eigen decompositor factory. */ public static final DecompositorFactory EIGEN = DecompositorFactory.EIGEN; /** * Reference to Raw LU decompositor factory. */ public static final DecompositorFactory RAW_LU = DecompositorFactory.RAW_LU; /** * Reference to LU decompositor factory. */ public static final DecompositorFactory LU = DecompositorFactory.LU; /** * Reference to Raw QR decompositor factory. */ public static final DecompositorFactory RAW_QR = DecompositorFactory.RAW_QR; /** * Reference to QR decompositor factory. */ public static final DecompositorFactory QR = DecompositorFactory.QR; /** * Reference to SVD decompositor factory. */ public static final DecompositorFactory SVD = DecompositorFactory.SVD; public final static VectorVectorOperation OO_PLACE_INNER_PRODUCT = new OoPlaceInnerProduct(); public final static VectorVectorOperation OO_PLACE_VECTORS_ADDITION = new OoPlaceVectorsAddition(); public final static VectorVectorOperation OO_PLACE_VECTOR_HADAMARD_PRODUCT = new OoPlaceVectorHadamardProduct(); public final static VectorVectorOperation OO_PLACE_VECTORS_SUBTRACTION = new OoPlaceVectorsSubtraction(); public final static VectorMatrixOperation OO_PLACE_VECTOR_BY_MATRIX_MULTIPLICATION = new OoPlaceVectorByMatrixMultiplication(); public final static VectorVectorOperation OO_PLACE_OUTER_PRODUCT = new OoPlaceOuterProduct(); public final static MatrixMatrixOperation IN_PLACE_COPY_MATRIX_TO_MATRIX = new InPlaceCopyMatrixToMatrix(); public final static MatrixMatrixOperation OO_PLACE_MATRIX_ADDITION = new OoPlaceMatricesAddition(); public final static MatrixVectorOperation OO_PLACE_MATRIX_BY_VECTOR_MULTIPLICATION = new OoPlaceMatrixByVectorMultiplication(); public final static MatrixMatrixOperation OO_PLACE_MATRICES_SUBTRACTION = new OoPlaceMatricesSubtraction(); public final static MatrixMatrixOperation OO_PLACE_MATRIX_HADAMARD_PRODUCT = new OoPlaceMatrixHadamardProduct(); public final static MatrixOperation OO_PLACE_MATRIX_BY_ITS_TRANSPOSE_MULTIPLICATION = new OoPlaceMatrixByItsTransposeMultiplication(); public final static MatrixMatrixOperation OO_PLACE_KRONECKER_PRODUCT = new OoPlaceKroneckerProduct(); public final static MatrixMatrixOperation OO_PLACE_MATRICES_MULTIPLICATION = new OoPlaceMatricesMultiplication(); } la4j-0.6.0/src/main/java/org/la4j/Matrices.java000066400000000000000000000550761263320764000210560ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Yuriy Drozd * Ewald Grusk * Maxim Samoylov * Miron Aseev * Todd Brunhoff * */ package org.la4j; import java.math.BigDecimal; import java.math.RoundingMode; import org.la4j.matrix.MatrixFactory; import org.la4j.matrix.dense.Basic1DMatrix; import org.la4j.matrix.dense.Basic2DMatrix; import org.la4j.matrix.functor.AdvancedMatrixPredicate; import org.la4j.matrix.functor.MatrixAccumulator; import org.la4j.matrix.functor.MatrixFunction; import org.la4j.matrix.functor.MatrixPredicate; import org.la4j.matrix.functor.MatrixProcedure; import org.la4j.matrix.sparse.CCSMatrix; import org.la4j.matrix.sparse.CRSMatrix; public final class Matrices { /** * The machine epsilon, that is calculated at runtime. */ public static final double EPS = LinearAlgebra.EPS; /** * Exponent of machine epsilon */ public static final int ROUND_FACTOR = LinearAlgebra.ROUND_FACTOR; /** * Checks whether the matrix is a * diagonal * matrix. */ public static final MatrixPredicate DIAGONAL_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return rows == columns; } @Override public boolean test(int i, int j, double value) { return (i == j) || Math.abs(value) < EPS; } }; /** * Checks whether the matrix is an * identity * matrix. */ public static final MatrixPredicate IDENTITY_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return rows == columns; } @Override public boolean test(int i, int j, double value) { return (i == j) ? Math.abs(1.0 - value) < EPS : Math.abs(value) < EPS; } }; /** * Checks whether the matrix is a * zero * matrix. */ public static final MatrixPredicate ZERO_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return true; } @Override public boolean test(int i, int j, double value) { return Math.abs(value) < EPS; } }; /** * Checks whether the matrix is a * tridiagonal * matrix. */ public static final MatrixPredicate TRIDIAGONAL_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return rows == columns; } @Override public boolean test(int i, int j, double value) { return Math.abs(i - j) <= 1 || Math.abs(value) < EPS; } }; /** * Checks whether the matrix is a * positive * matrix. */ public static final MatrixPredicate POSITIVE_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return true; } @Override public boolean test(int i, int j, double value) { return value > 0.0; } }; /** * Checks whether the matrix is a * negative * matrix. */ public static final MatrixPredicate NEGATIVE_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return true; } @Override public boolean test(int i, int j, double value) { return value < 0.0; } }; /** * Checks whether the matrix is a lower bi-diagonal matrix. */ public static final MatrixPredicate LOWER_BIDIAGONAL_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return rows == columns; } @Override public boolean test(int i, int j, double value) { return !((i == j) || (i == j + 1)) || Math.abs(value) < EPS; } }; /** * Checks whether the matrix is an upper bidiagonal matrix. */ public static final MatrixPredicate UPPER_BIDIAGONAL_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return rows == columns; } @Override public boolean test(int i, int j, double value) { return !((i == j) || (i == j - 1)) || Math.abs(value) < EPS; } }; /** * Checks whether the matrix is a * lower * triangular matrix. */ public static final MatrixPredicate LOWER_TRIANGULAR_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return rows == columns; } @Override public boolean test(int i, int j, double value) { return (i <= j) || Math.abs(value) < EPS; } }; /** * Checks whether the matrix is an * upper * triangular matrix. */ public static final MatrixPredicate UPPER_TRIANGULAR_MATRIX = new MatrixPredicate() { @Override public boolean test(int rows, int columns) { return rows == columns; } @Override public boolean test(int i, int j, double value) { return (i >= j) || Math.abs(value) < EPS; } }; private static class SymmetricMatrixPredicate implements AdvancedMatrixPredicate { @Override public boolean test(Matrix matrix) { if (matrix.rows() != matrix.columns()) { return false; } for (int i = 0; i < matrix.rows(); i++) { for (int j = i + 1; j < matrix.columns(); j++) { double a = matrix.get(i, j); double b = matrix.get(j, i); double diff = Math.abs(a - b); if (diff / Math.max(Math.abs(a), Math.abs(b)) > EPS) { return false; } } } return true; } } private static class DiagonallyDominantPredicate implements AdvancedMatrixPredicate { @Override public boolean test(Matrix matrix) { if (matrix.rows() != matrix.columns()) { return false; } for (int i = 0; i < matrix.rows(); i++) { double sum = 0; for (int j = 0; j < matrix.columns(); j++) { if (i != j) { sum += Math.abs(matrix.get(i, j)); } } if (sum > Math.abs(matrix.get(i, i)) - EPS) { return false; } } return true; } } private static class PositiveDefiniteMatrixPredicate implements AdvancedMatrixPredicate { @Override public boolean test(Matrix matrix) { if (matrix.rows() != matrix.columns()) { return false; } int size = matrix.columns(); int currentSize = 1; while (currentSize <= size) { Matrix topLeftMatrix = matrix.sliceTopLeft(currentSize, currentSize); if (topLeftMatrix.determinant() < 0) { return false; } currentSize++; } return true; } } /** * Checks whether the matrix is a * symmetric * matrix. */ public static final AdvancedMatrixPredicate SYMMETRIC_MATRIX = new SymmetricMatrixPredicate(); /** * Checks whether the matrix is a * diagonally dominant matrix. */ public static final AdvancedMatrixPredicate DIAGONALLY_DOMINANT_MATRIX = new DiagonallyDominantPredicate(); /** * Checks whether the matrix is positive definite. */ public static final AdvancedMatrixPredicate POSITIVE_DEFINITE_MATRIX = new PositiveDefiniteMatrixPredicate(); /** * A matrix factory that produces zero {@link Basic2DMatrix}. */ public static final MatrixFactory BASIC_2D = new MatrixFactory() { @Override public Basic2DMatrix apply(int rows, int columns) { return Basic2DMatrix.zero(rows, columns); } }; /** * A matrix factory that produces zero {@link Basic1DMatrix}. */ public static final MatrixFactory BASIC_1D = new MatrixFactory() { @Override public Basic1DMatrix apply(int rows, int columns) { return Basic1DMatrix.zero(rows, columns); } }; /** * A default matrix factory for dense matrices. */ public static final MatrixFactory DENSE = BASIC_2D; /** * A matrix factory that produces zero {@link CCSMatrix}. */ public static final MatrixFactory CCS = new MatrixFactory() { @Override public CCSMatrix apply(int rows, int columns) { return CCSMatrix.zero(rows, columns); } }; /** * A matrix factory that produces zero {@link CRSMatrix}. */ public static final MatrixFactory CRS = new MatrixFactory() { @Override public CRSMatrix apply(int rows, int columns) { return CRSMatrix.zero(rows, columns); } }; /** * A default factory for sparse matrices. */ public static final MatrixFactory SPARSE = CRS; /** * A default factory for sparse row-major matrices. */ public static final MatrixFactory SPARSE_ROW_MAJOR = CRS; /** * A default factory for sparse column-major matrices. */ public static final MatrixFactory SPARSE_COLUMN_MAJOR = CCS; public static final MatrixFactory[] CONVERTERS = { BASIC_2D, BASIC_1D, CRS, CCS }; /** * Increases each element of matrix by 1. */ public static final MatrixFunction INC_FUNCTION = new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return value + 1.0; } }; /** * Decreases each element of matrix by 1. */ public static final MatrixFunction DEC_FUNCTION = new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return value - 1.0; } }; /** * Inverts each element of matrix. */ public static final MatrixFunction INV_FUNCTION = new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return -value; } }; /** * Creates a const function that evaluates it's argument to given {@code value}. * * @param arg a const value * * @return a closure object that does {@code _} */ public static MatrixFunction asConstFunction(final double arg) { return new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return arg; } }; } /** * Creates a plus function that adds given {@code value} to it's argument. * * @param arg a value to be added to function's argument * * @return a closure object that does {@code _ + _} */ public static MatrixFunction asPlusFunction(final double arg) { return new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return value + arg; } }; } /** * Creates a minus function that subtracts given {@code value} from it's argument. * * @param arg a value to be subtracted from function's argument * * @return a closure that does {@code _ - _} */ public static MatrixFunction asMinusFunction(final double arg) { return new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return value - arg; } }; } /** * Creates a mul function that multiplies given {@code value} by it's argument. * * @param arg a value to be multiplied by function's argument * * @return a closure that does {@code _ * _} */ public static MatrixFunction asMulFunction(final double arg) { return new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return value * arg; } }; } /** * Creates a div function that divides it's argument by given {@code value}. * * @param arg a divisor value * * @return a closure that does {@code _ / _} */ public static MatrixFunction asDivFunction(final double arg) { return new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return value / arg; } }; } /** * Creates a mod function that calculates the modulus of it's argument and given {@code value}. * * @param arg a divisor value * * @return a closure that does {@code _ % _} */ public static MatrixFunction asModFunction(final double arg) { return new MatrixFunction() { @Override public double evaluate(int i, int j, double value) { return value % arg; } }; } /** * Makes a minimum matrix accumulator that accumulates the minimum of matrix elements. * * @return a minimum vector accumulator */ public static MatrixAccumulator mkMinAccumulator() { return new MatrixAccumulator() { private double result = Double.POSITIVE_INFINITY; @Override public void update(int i, int j, double value) { result = Math.min(result, value); } @Override public double accumulate() { double value = result; result = Double.POSITIVE_INFINITY; return value; } }; } /** * Makes a maximum matrix accumulator that accumulates the maximum of matrix elements. * * @return a maximum vector accumulator */ public static MatrixAccumulator mkMaxAccumulator() { return new MatrixAccumulator() { private double result = Double.NEGATIVE_INFINITY; @Override public void update(int i, int j, double value) { result = Math.max(result, value); } @Override public double accumulate() { double value = result; result = Double.NEGATIVE_INFINITY; return value; } }; } /** * Makes an Euclidean norm accumulator that allows to use * {@link org.la4j.Matrix#fold(org.la4j.vector.functor.MatrixAccumulator)} * method for norm calculation. * * @return an Euclidean norm accumulator */ public static MatrixAccumulator mkEuclideanNormAccumulator() { return new MatrixAccumulator() { private BigDecimal result = new BigDecimal(0.0); @Override public void update(int i, int j, double value) { result = result.add(new BigDecimal(value * value)); } @Override public double accumulate() { double value = result.setScale(Matrices.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = new BigDecimal(0.0); return Math.sqrt(value); } }; } /** * Makes an Manhattan norm accumulator that allows to use * {@link org.la4j.Matrix#fold(org.la4j.vector.functor.MatrixAccumulator)} * method for norm calculation. * * @return a Manhattan norm accumulator */ public static MatrixAccumulator mkManhattanNormAccumulator() { return new MatrixAccumulator() { private double result = 0.0; @Override public void update(int i, int j, double value) { result += Math.abs(value); } @Override public double accumulate() { double value = result; result = 0.0; return value; } }; } /** * Makes an Infinity norm accumulator that allows to use * {@link org.la4j.Matrix#fold(org.la4j.vector.functor.MatrixAccumulator)} * method for norm calculation. * * @return an Infinity norm accumulator */ public static MatrixAccumulator mkInfinityNormAccumulator() { return new MatrixAccumulator() { private double result = Double.NEGATIVE_INFINITY; @Override public void update(int i, int j, double value) { result = Math.max(result, Math.abs(value)); } @Override public double accumulate() { double value = result; result = Double.NEGATIVE_INFINITY; return value; } }; } /** * Creates a sum matrix accumulator that calculates the sum of all elements in the matrix. * * @param neutral the neutral value * * @return a sum accumulator */ public static MatrixAccumulator asSumAccumulator(final double neutral) { return new MatrixAccumulator() { private BigDecimal result = new BigDecimal(neutral); @Override public void update(int i, int j, double value) { result = result.add(new BigDecimal(value)); } @Override public double accumulate() { double value = result.setScale(Matrices.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = new BigDecimal(neutral); return value; } }; } /** * Creates a product matrix accumulator that calculates the product of all elements in the matrix. * * @param neutral the neutral value * * @return a product accumulator */ public static MatrixAccumulator asProductAccumulator(final double neutral) { return new MatrixAccumulator() { private BigDecimal result = new BigDecimal(neutral); @Override public void update(int i, int j, double value) { result = result.multiply(new BigDecimal(value)); } @Override public double accumulate() { double value = result.setScale(Matrices.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = new BigDecimal(neutral); return value; } }; } /** * Creates a sum function accumulator, that calculates the sum of all * elements in the matrix after applying given {@code function} to each of them. * * @param neutral the neutral value * @param function the matrix function * * @return a sum function accumulator */ public static MatrixAccumulator asSumFunctionAccumulator(final double neutral, final MatrixFunction function) { return new MatrixAccumulator() { private final MatrixAccumulator sumAccumulator = Matrices.asSumAccumulator(neutral); @Override public void update(int i, int j, double value) { sumAccumulator.update(i, j, function.evaluate(i, j, value)); } @Override public double accumulate() { return sumAccumulator.accumulate(); } }; } /** * Creates a product function accumulator, that calculates the product of * all elements in the matrix after applying given {@code function} to * each of them. * * @param neutral the neutral value * @param function the matrix function * * @return a product function accumulator */ public static MatrixAccumulator asProductFunctionAccumulator(final double neutral, final MatrixFunction function) { return new MatrixAccumulator() { private final MatrixAccumulator productAccumulator = Matrices.asProductAccumulator(neutral); @Override public void update(int i, int j, double value) { productAccumulator.update(i, j, function.evaluate(i, j, value)); } @Override public double accumulate() { return productAccumulator.accumulate(); } }; } /** * Creates an accumulator procedure that adapts a matrix accumulator for procedure * interface. This is useful for reusing a single accumulator for multiple fold operations * in multiple matrices. * * @param accumulator the matrix accumulator * * @return an accumulator procedure */ public static MatrixProcedure asAccumulatorProcedure(final MatrixAccumulator accumulator) { return new MatrixProcedure() { @Override public void apply(int i, int j, double value) { accumulator.update(i, j, value); } }; } }la4j-0.6.0/src/main/java/org/la4j/Matrix.java000066400000000000000000001717331263320764000205520ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Evgenia Krivova * Julia Kostyukova * Jakob Moellers * Maxim Samoylov * Anveshi Charuvaka * Todd Brunhoff * Pavel Kalaidin * Ewald Grusk * Yuriy Drozd */ package org.la4j; import org.la4j.decomposition.MatrixDecompositor; import org.la4j.inversion.MatrixInverter; import org.la4j.iterator.ColumnMajorMatrixIterator; import org.la4j.iterator.MatrixIterator; import org.la4j.iterator.RowMajorMatrixIterator; import org.la4j.iterator.VectorIterator; import org.la4j.linear.LinearSystemSolver; import org.la4j.matrix.MatrixFactory; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.dense.Basic1DMatrix; import org.la4j.matrix.dense.Basic2DMatrix; import org.la4j.matrix.functor.*; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.matrix.SparseMatrix; import org.la4j.operation.MatrixMatrixOperation; import org.la4j.operation.MatrixOperation; import org.la4j.operation.MatrixVectorOperation; import org.la4j.vector.functor.VectorAccumulator; import org.la4j.vector.functor.VectorFunction; import org.la4j.vector.functor.VectorProcedure; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Random; import java.util.StringTokenizer; /** * A real matrix. *

* * http://mathworld.wolfram.com/Matrix.html *

*/ public abstract class Matrix implements Iterable { private static final String DEFAULT_ROWS_DELIMITER = "\n"; private static final String DEFAULT_COLUMNS_DELIMITER = " "; private static final NumberFormat DEFAULT_FORMATTER = new DecimalFormat("0.000"); private static final String[] INDENTS = { // 9 predefined indents for alignment " ", " ", " ", " ", " ", " ", " ", " ", " ", " " }; /** * Creates a zero {@link Matrix} of the given shape: * {@code rows} x {@code columns}. */ public static Matrix zero(int rows, int columns) { long size = (long) rows * columns; return size > 1000 ? SparseMatrix.zero(rows, columns) : DenseMatrix.zero(rows, columns); } /** * Creates a constant {@link Matrix} of the given shape and {@code value}. */ public static Matrix constant(int rows, int columns, double constant) { return DenseMatrix.constant(rows, columns, constant); } /** * Creates a diagonal {@link Matrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static Matrix diagonal(int size, double diagonal) { return SparseMatrix.diagonal(size, diagonal); } /** * Creates an unit {@link Matrix} of the given shape: * {@code rows} x {@code columns}. */ public static Matrix unit(int rows, int columns) { return DenseMatrix.unit(rows, columns); } /** * Creates an identity {@link Matrix} of the given {@code size}. */ public static Matrix identity(int size) { return SparseMatrix.identity(size); } /** * Creates a random {@link Matrix} of the given shape: * {@code rows} x {@code columns}. */ public static Matrix random(int rows, int columns, Random random) { return DenseMatrix.random(rows, columns, random); } /** * Creates a random symmetric {@link Matrix} of the given {@code size}. */ public static Matrix randomSymmetric(int size, Random random) { return DenseMatrix.randomSymmetric(size, random); } /** * Creates a {@link Matrix} of the given 1D {@code array} w/o * copying the underlying array. */ public static Matrix from1DArray(int rows, int columns, double[] array) { return Basic1DMatrix.from1DArray(rows, columns, array); } /** * Creates a {@link Matrix} of the given 2D {@code array} w/o * copying the underlying array. */ public static Matrix from2DArray(double[][] array) { return Basic2DMatrix.from2DArray(array); } /** * Creates a block {@link Matrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static Matrix block(Matrix a, Matrix b, Matrix c, Matrix d) { return DenseMatrix.block(a, b, c, d); } /** * Parses {@link Matrix} from the given CSV string. * * @param csv the string in CSV format * * @return a parsed matrix */ public static Matrix fromCSV(String csv) { StringTokenizer lines = new StringTokenizer(csv, "\n"); Matrix result = DenseMatrix.zero(10, 10); int rows = 0, columns = 0; while (lines.hasMoreTokens()) { if (result.rows() == rows) { result = result.copyOfRows((rows * 3) / 2 + 1); } StringTokenizer elements = new StringTokenizer(lines.nextToken(), ", "); int j = 0; while (elements.hasMoreElements()) { if (j == result.columns()) { result = result.copyOfColumns((j * 3) / 2 + 1); } double x = Double.valueOf(elements.nextToken()); result.set(rows, j++, x); } rows++; columns = j > columns ? j : columns; } return result.copyOfShape(rows, columns); } /** * Parses {@link Matrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static Matrix fromMatrixMarket(String mm) { StringTokenizer body = new StringTokenizer(mm, "\n"); String headerString = body.nextToken(); StringTokenizer header = new StringTokenizer(headerString); if (!"%%MatrixMarket".equals(header.nextToken())) { throw new IllegalArgumentException("Wrong input file format: can not read header '%%MatrixMarket'."); } String object = header.nextToken(); if (!"matrix".equals(object)) { throw new IllegalArgumentException("Unexpected object: " + object + "."); } String format = header.nextToken(); if (!"coordinate".equals(format) && !"array".equals(format)) { throw new IllegalArgumentException("Unknown format: " + format + "."); } String field = header.nextToken(); if (!"real".equals(field)) { throw new IllegalArgumentException("Unknown field type: " + field + "."); } String symmetry = header.nextToken(); if (!symmetry.equals("general")) { throw new IllegalArgumentException("Unknown symmetry type: " + symmetry + "."); } String majority = (header.hasMoreTokens()) ? header.nextToken() : "row-major"; String nextToken = body.nextToken(); while (nextToken.startsWith("%")) { nextToken = body.nextToken(); } if ("coordinate".equals(format)) { StringTokenizer lines = new StringTokenizer(nextToken); int rows = Integer.valueOf(lines.nextToken()); int columns = Integer.valueOf(lines.nextToken()); int cardinality = Integer.valueOf(lines.nextToken()); Matrix result = "row-major".equals(majority) ? RowMajorSparseMatrix.zero(rows, columns, cardinality) : ColumnMajorSparseMatrix.zero(rows, columns, cardinality); for (int k = 0; k < cardinality; k++) { lines = new StringTokenizer(body.nextToken()); int i = Integer.valueOf(lines.nextToken()); int j = Integer.valueOf(lines.nextToken()); double x = Double.valueOf(lines.nextToken()); result.set(i - 1, j - 1, x); } return result; } else { StringTokenizer lines = new StringTokenizer(nextToken); int rows = Integer.valueOf(lines.nextToken()); int columns = Integer.valueOf(lines.nextToken()); Matrix result = DenseMatrix.zero(rows, columns); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { result.set(i, j, Double.valueOf(body.nextToken())); } } return result; } } protected int rows; protected int columns; /** * Creates a zero-shape matrix. */ public Matrix() { this(0, 0); } /** * Creates a matrix of given shape {@code rows} x {@code columns}; */ public Matrix(int rows, int columns) { ensureDimensionsAreCorrect(rows, columns); this.rows = rows; this.columns = columns; } // // ============ ABSTRACT METHODS ============ // /** * Gets the specified element of this matrix. * * @param i element's row index * @param j element's column index * * @return the element of this matrix */ public abstract double get(int i, int j); /** * Sets the specified element of this matrix to given {@code value}. * * @param i element's row index * @param j element's column index * @param value element's new value */ public abstract void set(int i, int j, double value); /** * Copies the specified row of this matrix into the vector. * * @param i the row index * * @return the row represented as vector */ public abstract Vector getRow(int i); /** * Copies the specified column of this matrix into the vector. * * @param j the column index * * @return the column represented as vector */ public abstract Vector getColumn(int j); /** * Creates the blank matrix (a zero matrix with same size) of this matrix * of the given shape: {@code rows} x {@code columns}. * * @return blank matrix */ public abstract Matrix blankOfShape(int rows, int columns); /** * Copies this matrix into the new matrix with specified dimensions: {@code rows} and {@code columns}. * * @param rows the number of rows in new matrix * @param columns the number of columns in new matrix * * @return the copy of this matrix with new size */ public abstract Matrix copyOfShape(int rows, int columns); /** * Pipes this matrix to a given {@code operation}. * * @param operation the matrix operation * (an operation that takes a matrix and returns {@code T}) * @param the result type * * @return the result of an operation applied to this matrix */ public abstract T apply(MatrixOperation operation); /** * Pipes this matrix to a given {@code operation}. * * @param operation the matrix-matrix operation * (an operation that takes two matrices and returns {@code T}) * @param that the right hand matrix of the given operation * @param the result type * * @return the result of an operation applied to this matrix */ public abstract T apply(MatrixMatrixOperation operation, Matrix that); /** * Pipes this matrix to a given {@code operation}. * * @param operation the matrix-vector operation * (an operation that takes matrix and vector and returns {@code T}) * @param that the right hand vector of the given operation * @param the result type * * @return the result of an operation applied to this matrix */ public abstract T apply(MatrixVectorOperation operation, Vector that); /** * Encodes this matrix into a byte array. * * @return a byte array representing this matrix */ public abstract byte[] toBinary(); /** * Converts this matrix into the Matrix Market string using the * given number {@code formatter}. * * @return a string in Matrix Market format representing this matrix; */ public abstract String toMatrixMarket(NumberFormat formatter); // // ============ CONCRETE METHODS ============ // /** * Sets all elements of this matrix to the given {@code value}. * * @param value the element's new value */ public void setAll(double value) { MatrixIterator it = iterator(); while (it.hasNext()) { it.next(); it.set(value); } } /** *

* Sets all elements of the specified row of this matrix to given {@code value}. *

* * @param i the row index * @param value the element's new value */ public void setRow(int i, double value) { VectorIterator it = iteratorOfRow(i); while (it.hasNext()) { it.next(); it.set(value); } } /** *

* Sets all elements of the specified column of this matrix to given {@code value}. *

* * @param j the column index * @param value the element's new value */ public void setColumn(int j, double value) { VectorIterator it = iteratorOfColumn(j); while (it.hasNext()) { it.next(); it.set(value); } } /** * Swaps the specified rows of this matrix. * * @param i the row index * @param j the row index */ public void swapRows(int i, int j) { if (i != j) { Vector ii = getRow(i); Vector jj = getRow(j); setRow(i, jj); setRow(j, ii); } } /** * Swaps the specified columns of this matrix. * * @param i the column index * @param j the column index */ public void swapColumns(int i, int j) { if (i != j) { Vector ii = getColumn(i); Vector jj = getColumn(j); setColumn(i, jj); setColumn(j, ii); } } /** * Returns the number of rows of this matrix. * * @return the number of rows */ public int rows() { return rows; } /** * Returns the number of columns of this matrix. * * @return the number of columns */ public int columns() { return columns; } /** * Transposes this matrix. * * @return the transposed matrix */ public Matrix transpose() { Matrix result = blankOfShape(columns, rows); MatrixIterator it = result.iterator(); while (it.hasNext()) { it.next(); int i = it.rowIndex(); int j = it.columnIndex(); it.set(get(j, i)); } return result; } /** * Rotates this matrix by 90 degrees to the right. * * @return the rotated matrix */ public Matrix rotate() { Matrix result = blankOfShape(columns, rows); MatrixIterator it = result.iterator(); while (it.hasNext()) { it.next(); int i = it.rowIndex(); int j = it.columnIndex(); it.set(get(rows - 1 - j, i)); } return result; } /** * Powers this matrix of given exponent {code n}. * * @param n the exponent * * @return the powered matrix */ public Matrix power(int n) { if (n < 0) { fail("The exponent should be positive: " + n + "."); } Matrix result = blankOfShape(rows, rows); Matrix that = this; for (int i = 0; i < rows; i++) { result.set(i, i, 1.0); } while (n > 0) { if (n % 2 == 1) { result = result.multiply(that); } n /= 2; that = that.multiply(that); } return result; } /** * Scales this matrix by given {@code value} (v). * * @param value the scale factor * * @return A * v */ public Matrix multiply(double value) { Matrix result = blank(); MatrixIterator it = iterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, x * value); } return result; } /** * Multiplies this matrix (A) by given {@code that} vector (x). * * @param that the vector * * @return A * x */ public Vector multiply(Vector that) { return apply(LinearAlgebra.OO_PLACE_MATRIX_BY_VECTOR_MULTIPLICATION, that); } /** * Multiplies this matrix (A) by given {@code that} matrix (B). * * @param that the right hand matrix for multiplication * * @return A * B */ public Matrix multiply(Matrix that) { return apply(LinearAlgebra.OO_PLACE_MATRICES_MULTIPLICATION, that); } /** * Multiplies this matrix by its transpose. * * @return this matrix multiplied by its transpose */ public Matrix multiplyByItsTranspose() { return apply(LinearAlgebra.OO_PLACE_MATRIX_BY_ITS_TRANSPOSE_MULTIPLICATION); } /** * Subtracts given {@code value} (v) from every element of this matrix (A). * * @param value the right hand value for subtraction * * @return A - v */ public Matrix subtract(double value) { return add(-value); } /** * Subtracts given {@code that} matrix (B) from this matrix (A). * * @param that the right hand matrix for subtraction * * @return A - B */ public Matrix subtract(Matrix that) { return apply(LinearAlgebra.OO_PLACE_MATRICES_SUBTRACTION, that); } /** * Adds given {@code value} (v) to every element of this matrix (A). * * @param value the right hand value for addition * * @return A + v */ public Matrix add(double value) { MatrixIterator it = iterator(); Matrix result = blank(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, x + value); } return result; } /** * Adds given {@code that} matrix (B) to this matrix (A). * * @param that the right hand matrix for addition * * @return A + B */ public Matrix add(Matrix that) { return apply(LinearAlgebra.OO_PLACE_MATRIX_ADDITION, that); } /** * Inserts a given {@code that} (B) into this matrix (A). The original * values are overwritten by the new ones. * * @param that the matrix to insert, from the first row and column * @return a matrix with the parameter inserted into it */ public Matrix insert(Matrix that) { return insert(that, 0, 0, 0, 0, that.rows(), that.columns()); } /** * Inserts a given {@code that} matrix (B) into this matrix (A). The original * values are overwritten by the new ones. * * @param that the matrix to insert * @param rows number of rows to insert * @param columns number of columns to insert * @return a matrix with the parameter inserted into it */ public Matrix insert(Matrix that, int rows, int columns) { return insert(that, 0, 0, 0, 0, rows, columns); } /** * Inserts a given {@code that} matrix (B) into this matrix (A). The original * values are overwritten by the new ones. * * @param that the matrix to insert * @param destRow the row to insert at in the destination matrix * @param destColumn the column to insert at in the destination matrix * @param rows number of rows to insert * @param columns number of columns to insert * @return a matrix with the parameter inserted into it */ public Matrix insert(Matrix that, int destRow, int destColumn, int rows, int columns) { return insert(that, 0, 0, destRow, destColumn, rows, columns); } /** * Inserts a given {@code that} matrix (B) into this matrix (A). The original * values are overwritten by the new ones. * * @param that the matrix to insert * @param srcRow the row to start at in the source matrix * @param srcColumn the column to start at in the source matrix * @param destRow the row to insert at in the destination matrix * @param destColumn the column to insert at in the destination matrix * @param rows number of rows to insert * @param columns number of columns to insert * @return a matrix with the parameter inserted into it */ public Matrix insert(Matrix that, int srcRow, int srcColumn, int destRow, int destColumn, int rows, int columns) { if (rows < 0 || columns < 0) { fail("Cannot have negative rows or columns: " + rows + "x" + columns); } if (destRow < 0 || destColumn < 0) { fail("Cannot have negative destination position: " + destRow + ", " + destColumn); } if (destRow > this.rows || destColumn > this.columns) { fail("Destination position out of bounds: " + destRow + ", " + destColumn); } if (srcRow < 0 || srcColumn < 0) { fail("Cannot have negative source position: " + destRow + ", " + destColumn); } if (srcRow > that.rows || srcColumn > that.columns) { fail("Destination position out of bounds: " + srcRow + ", " + srcColumn); } if (destRow + rows > this.rows || destColumn + columns > this.columns) { fail("Out of bounds: Cannot add " + rows + " rows and " + columns + " cols at " + destRow + ", " + destColumn + " in a " + this.rows + "x" + this.columns + " matrix."); } if (srcRow + rows > that.rows || srcColumn + columns > that.columns) { fail("Out of bounds: Cannot get " + rows + " rows and " + columns + " cols at " + srcRow + ", " + srcColumn + " from a " + that.rows + "x" + that.columns + " matrix."); } Matrix result = copy(); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { result.set(i + destRow, j + destColumn, that.get(i + srcRow, j + srcColumn)); } } return result; } /** * Divides every element of this matrix (A) by given {@code value} (v). * * @param value the right hand value for division * * @return A / v */ public Matrix divide(double value) { return multiply(1.0 / value); } /** * Calculates the Kronecker product of this matrix (A) and given {@code that} matrix (B). * * @param that the right hand matrix for Kronecker product * * @return A (+) B */ public Matrix kroneckerProduct(Matrix that) { return apply(LinearAlgebra.OO_PLACE_KRONECKER_PRODUCT, that); } /** * Calculates the trace of this matrix. * *

* See * http://mathworld.wolfram.com/MatrixTrace.html for more details. *

* * @return the trace of this matrix */ public double trace() { double result = 0.0; for (int i = 0; i < rows; i++) { result += get(i, i); } return result; } /** * Calculates the product of diagonal elements of this matrix. * * @return the product of diagonal elements of this matrix */ public double diagonalProduct() { BigDecimal result = BigDecimal.ONE; for (int i = 0; i < rows; i++) { result = result.multiply(BigDecimal.valueOf(get(i, i))); } return result.setScale(Matrices.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); } /** * Calculates an Euclidean norm of this matrix, a.k.a. frobenius norm * * @return an Euclidean norm */ public double norm() { return euclideanNorm(); } /** * Calculates an Euclidean norm of this matrix, a.k.a. frobenius norm * * @return an Euclidean norm */ public double euclideanNorm() { return fold(Matrices.mkEuclideanNormAccumulator()); } /** * Calculates a Manhattan norm of this matrix, a.k.a. taxicab norm * * @return a Manhattan norm */ public double manhattanNorm() { return fold(Matrices.mkManhattanNormAccumulator()); } /** * Calculates an Infinity norm of this matrix. * * @return an Infinity norm */ public double infinityNorm() { return fold(Matrices.mkInfinityNormAccumulator()); } /** * Multiplies up all elements of this matrix. * * @return the product of all elements of this matrix */ public double product() { return fold(Matrices.asProductAccumulator(1.0)); } /** * Summarizes up all elements of this matrix. * * @return the sum of all elements of this matrix */ public double sum() { return fold(Matrices.asSumAccumulator(0.0)); } /** * Calculates the Hadamard (element-wise) product of this and given {@code that} matrix. * * @param that the right hand matrix for Hadamard product * * @return the Hadamard product of two matrices */ public Matrix hadamardProduct(Matrix that) { return apply(LinearAlgebra.OO_PLACE_MATRIX_HADAMARD_PRODUCT, that); } /** * Calculates the determinant of this matrix. * *

* See * http://mathworld.wolfram.com/Determinant.html for more details. *

* * @return the determinant of this matrix */ public double determinant() { if (rows != columns) { throw new IllegalStateException("Can not compute determinant of non-square matrix."); } if (rows == 0) { return 0.0; } else if (rows == 1) { return get(0, 0); } else if (rows == 2) { return get(0, 0) * get(1, 1) - get(0, 1) * get(1, 0); } else if (rows == 3) { return get(0, 0) * get(1, 1) * get(2, 2) + get(0, 1) * get(1, 2) * get(2, 0) + get(0, 2) * get(1, 0) * get(2, 1) - get(0, 2) * get(1, 1) * get(2, 0) - get(0, 1) * get(1, 0) * get(2, 2) - get(0, 0) * get(1, 2) * get(2, 1); } MatrixDecompositor decompositor = withDecompositor(LinearAlgebra.LU); Matrix lup[] = decompositor.decompose(); // TODO: Why Java doesn't support pattern matching? Matrix u = lup[1]; Matrix p = lup[2]; double result = u.diagonalProduct(); // TODO: we can do that in O(n log n) // just google: "counting inversions divide and conqueror" int permutations[] = new int[p.rows()]; for (int i = 0; i < p.rows(); i++) { for (int j = 0; j < p.columns(); j++) { if (p.get(i, j) > 0.0) { permutations[i] = j; break; } } } int sign = 1; for (int i = 0; i < permutations.length; i++) { for (int j = i + 1; j < permutations.length; j++) { if (permutations[j] < permutations[i]) { sign *= -1; } } } return sign * result; } /** * Calculates the rank of this matrix. * *

* See * http://mathworld.wolfram.com/MatrixRank.html for more details. *

* * @return the rank of this matrix */ public int rank() { if (rows == 0 || columns == 0) { return 0; } // TODO: // handle small (1x1, 1xn, nx1, 2x2, 2xn, nx2, 3x3, 3xn, nx3) // matrices without SVD MatrixDecompositor decompositor = withDecompositor(LinearAlgebra.SVD); Matrix usv[] = decompositor.decompose(); // TODO: Where is my pattern matching? Matrix s = usv[1]; double tolerance = Math.max(rows, columns) * s.get(0, 0) * Matrices.EPS; int result = 0; for (int i = 0; i < s.rows(); i++) { if (s.get(i, i) > tolerance) { result++; } } return result; } /** * Copies given {@code row} into the specified row of this matrix. * * @param i the row index * @param row the row represented as vector */ public void setRow(int i, Vector row) { if (columns != row.length()) { fail("Wrong vector length: " + row.length() + ". Should be: " + columns + "."); } for (int j = 0; j < row.length(); j++) { set(i, j, row.get(j)); } } /** * Copies given {@code column} into the specified column of this matrix. * * @param j the column index * @param column the column represented as vector */ public void setColumn(int j, Vector column) { if (rows != column.length()) { fail("Wrong vector length: " + column.length() + ". Should be: " + rows + "."); } for (int i = 0; i < column.length(); i++) { set(i, j, column.get(i)); } } /** * Adds one row to matrix. * @param i the row index * @return matrix with row. */ public Matrix insertRow(int i, Vector row) { if (i >= rows || i < 0) { throw new IndexOutOfBoundsException("Illegal row number, must be 0.." + (rows - 1)); } Matrix result = blankOfShape(rows + 1, columns); for (int ii = 0; ii < i; ii++) { result.setRow(ii, getRow(ii)); } result.setRow(i, row); for (int ii = i; ii < rows; ii++) { result.setRow(ii + 1, getRow(ii)); } return result; } /** * Adds one column to matrix. * @param j the column index * @return matrix with column. */ public Matrix insertColumn(int j, Vector column) { if (j >= columns || j < 0) { throw new IndexOutOfBoundsException("Illegal row number, must be 0.." + (columns - 1)); } Matrix result = blankOfShape(rows, columns + 1); for (int jj = 0; jj < j; jj++) { result.setColumn(jj, getColumn(jj)); } result.setColumn(j, column); for (int jj = j; jj < columns; jj++) { result.setColumn(jj + 1, getColumn(jj)); } return result; } /** * Removes one row from matrix. * @param i the row index * @return matrix without row. */ public Matrix removeRow(int i) { if (i >= rows || i < 0) { throw new IndexOutOfBoundsException("Illegal row number, must be 0.." + (rows - 1)); } Matrix result = blankOfShape(rows - 1, columns); for (int ii = 0; ii < i; ii++) { result.setRow(ii, getRow(ii)); } for (int ii = i + 1; ii < rows; ii++) { result.setRow(ii - 1, getRow(ii)); } return result; } /** * Removes one column from matrix. * @param j the column index * @return matrix without column. */ public Matrix removeColumn(int j) { if (j >= columns || j < 0) { throw new IndexOutOfBoundsException("Illegal row number, must be 0.." + (columns - 1)); } Matrix result = blankOfShape(rows, columns - 1); for (int jj = 0; jj < j; jj++) { result.setColumn(jj, getColumn(jj)); } for (int jj = j + 1; jj < columns; jj++) { result.setColumn(jj - 1, getColumn(jj)); } return result; } /** * Removes first row from matrix. * @return matrix without first row. */ public Matrix removeFirstRow() { return removeRow(0); } /** * Removes first column from matrix. * @return matrix without first column */ public Matrix removeFirstColumn() { return removeColumn(0); } /** * Removes last row from matrix. * @return matrix without last row */ public Matrix removeLastRow() { return removeRow(rows - 1); } /** * Removes last column from matrix. * @return matrix without last column */ public Matrix removeLastColumn() { return removeColumn(columns - 1); } /** * Creates the blank matrix (a zero matrix with same size) of this matrix. * * @return blank matrix */ public Matrix blank() { return blankOfShape(rows, columns); } /** * Creates the blank matrix (a zero matrix with same size) of this matrix * of the given shape: {@code rows}. The {@code columns} number remains the * same. * * @return blank matrix */ public Matrix blankOfRows(int rows) { return blankOfShape(rows, columns); } /** * Creates the blank matrix (a zero matrix with same size) of this matrix * of the given shape: {@code columns}. The {@code rows} number remains the * same. * * @return blank matrix */ public Matrix blankOfColumns(int columns) { return blankOfShape(rows, columns); } /** * Copies this matrix. * * @return the copy of this matrix */ public Matrix copy() { return copyOfShape(rows, columns); } /** * Copies this matrix into the new matrix with specified row dimension: {@code rows}. * * @param rows the number of rows in new matrix * * @return the copy of this matrix with new size */ public Matrix copyOfRows(int rows) { return copyOfShape(rows, columns); } /** * Copies this matrix into the new matrix with specified column dimension: {@code columns}. * * @param columns the number of columns in new matrix * * @return the copy of this matrix with new size */ public Matrix copyOfColumns(int columns) { return copyOfShape(rows, columns); } /** * Shuffles this matrix. * *

* Copies this matrix into the matrix that contains the same elements but with the elements * shuffled around (which might also result in the same matrix (with a small likelihood)). *

* * @return the shuffled matrix */ public Matrix shuffle() { Matrix result = copy(); // Conduct Fisher-Yates shuffle Random random = new Random(); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { int ii = random.nextInt(rows - i) + i; int jj = random.nextInt(columns - j) + j; double a = result.get(ii, jj); result.set(ii, jj, result.get(i, j)); result.set(i, j, a); } } return result; } /** * Retrieves the specified sub-matrix of this matrix. The sub-matrix is specified by * intervals for row indices and column indices. * * @param fromRow the beginning of the row indices interval * @param fromColumn the beginning of the column indices interval * @param untilRow the ending of the row indices interval * @param untilColumn the ending of the column indices interval * * @return the sub-matrix of this matrix */ public Matrix slice(int fromRow, int fromColumn, int untilRow, int untilColumn) { if (untilRow - fromRow < 0 || untilColumn - fromColumn < 0) { fail("Wrong slice range: [" + fromRow + ".." + untilRow + "][" + fromColumn + ".." + untilColumn + "]."); } Matrix result = blankOfShape(untilRow - fromRow, untilColumn - fromColumn); for (int i = fromRow; i < untilRow; i++) { for (int j = fromColumn; j < untilColumn; j++) { result.set(i - fromRow, j - fromColumn, get(i, j)); } } return result; } /** * Retrieves the specified sub-matrix of this matrix. The sub-matrix is specified by * intervals for row indices and column indices. The top left points of both intervals * are fixed to zero. * * @param untilRow the ending of the row indices interval * @param untilColumn the ending of the column indices interval * * @return the sub-matrix of this matrix */ public Matrix sliceTopLeft(int untilRow, int untilColumn) { return slice(0, 0, untilRow, untilColumn); } /** * Retrieves the specified sub-matrix of this matrix. The sub-matrix is specified by * intervals for row indices and column indices. The bottom right points of both intervals * are fixed to matrix dimensions - it's rows and columns correspondingly. * * @param fromRow the beginning of the row indices interval * @param fromColumn the beginning of the column indices interval * * @return the sub-matrix of this matrix */ public Matrix sliceBottomRight(int fromRow, int fromColumn) { return slice(fromRow, fromColumn, rows, columns); } /** * Returns a new matrix with the selected rows and columns. This method can * be used either return a specific subset of rows and/or columns or to * permute the indices in an arbitrary order. The list of indices are * allowed to contain duplicates indices. This is more general than slice() * which selects only contiguous blocks. However, where applicable slice() * is probably more efficient. * * @param rowIndices the array of row indices * @param columnIndices the array of column indices * * @return the new matrix with the selected rows and columns * * @throws IllegalArgumentException if invalid row or column indices are provided */ public Matrix select(int[] rowIndices, int[] columnIndices) { int m = rowIndices.length; int n = columnIndices.length; if (m == 0 || n == 0) { fail("No rows or columns selected."); } Matrix result = blankOfShape(m, n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { result.set(i, j, get(rowIndices[i], columnIndices[j])); } } return result; } /** * Applies given {@code procedure} to each element of this matrix. * * @param procedure the matrix procedure */ public void each(MatrixProcedure procedure) { MatrixIterator it = iterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); procedure.apply(i, j, x); } } /** * Applies given {@code procedure} to each element of specified row of this matrix. * * @param i the row index * @param procedure the vector procedure */ public void eachInRow(int i, VectorProcedure procedure) { VectorIterator it = iteratorOfRow(i); while (it.hasNext()) { double x = it.next(); int j = it.index(); procedure.apply(j, x); } } /** * Applies given {@code procedure} to each element of specified column of this matrix. * * @param j the column index * @param procedure the vector procedure */ public void eachInColumn(int j, VectorProcedure procedure) { VectorIterator it = iteratorOfColumn(j); while (it.hasNext()) { double x = it.next(); int i = it.index(); procedure.apply(i, x); } } /** * Searches for the maximum value of the elements of this matrix. * * @return maximum value of this matrix */ public double max() { return fold(Matrices.mkMaxAccumulator()); } /** * Searches for the minimum value of the elements of this matrix. * * @return minimum value of this matrix */ public double min() { return fold(Matrices.mkMinAccumulator()); } /** * Searches for the maximum value of specified row in this matrix. * * @param i the row index * * @return maximum value of specified row in this matrix */ public double maxInRow(int i) { return foldRow(i, Vectors.mkMaxAccumulator()); } /** * Searches for the minimum value of specified row in this matrix. * * @param i the row index * * @return minimum value of specified row in this matrix */ public double minInRow(int i) { return foldRow(i, Vectors.mkMinAccumulator()); } /** * Searches for the maximum value of specified column in this matrix. * * @param j the column index * * @return maximum value of specified column in this matrix */ public double maxInColumn(int j) { return foldColumn(j, Vectors.mkMaxAccumulator()); } /** * Searches for the minimum value of specified column in this matrix. * * @param j the column index * * @return minimum value of specified column in this matrix */ public double minInColumn(int j) { return foldColumn(j, Vectors.mkMinAccumulator()); } /** * Builds a new matrix by applying given {@code function} to each element of this matrix. * * @param function the matrix function * * @return the transformed matrix */ public Matrix transform(MatrixFunction function) { Matrix result = blank(); MatrixIterator it = iterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, function.evaluate(i, j, x)); } return result; } /** * Builds a new matrix by applying given {@code function} to each element of specified * row in this matrix. * * @param i the row index * @param function the vector function * * @return the transformed matrix */ public Matrix transformRow(int i, VectorFunction function) { Matrix result = copy(); VectorIterator it = result.iteratorOfRow(i); while (it.hasNext()) { double x = it.next(); int j = it.index(); it.set(function.evaluate(j, x)); } return result; } /** * Builds a new matrix by applying given {@code function} to each element of specified * column in this matrix. * * @param j the column index * @param function the vector function * * @return the transformed matrix */ public Matrix transformColumn(int j, VectorFunction function) { Matrix result = copy(); VectorIterator it = result.iteratorOfColumn(j); while (it.hasNext()) { double x = it.next(); int i = it.index(); it.set(function.evaluate(i, x)); } return result; } /** * Updates all elements of this matrix by applying given {@code function}. * * @param function the matrix function */ public void update(MatrixFunction function) { MatrixIterator it = iterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); it.set(function.evaluate(i, j, x)); } } /** * Updates the specified element of this matrix by applying given {@code function}. * * @param i the row index * @param j the column index * @param function the matrix function */ public void updateAt(int i, int j, MatrixFunction function) { set(i, j, function.evaluate(i, j, get(i, j))); } /** * Updates all elements of the specified row in this matrix by applying given {@code function}. * * @param i the row index * @param function the vector function */ public void updateRow(int i, VectorFunction function) { VectorIterator it = iteratorOfRow(i); while (it.hasNext()) { double x = it.next(); int j = it.index(); it.set(function.evaluate(j, x)); } } /** * Updates all elements of the specified column in this matrix by applying given {@code function}. * * @param j the column index * @param function the vector function */ public void updateColumn(int j, VectorFunction function) { VectorIterator it = iteratorOfColumn(j); while (it.hasNext()) { double x = it.next(); int i = it.index(); it.set(function.evaluate(i, x)); } } /** * Folds all elements of this matrix with given {@code accumulator}. * * @param accumulator the matrix accumulator * * @return the accumulated value */ public double fold(MatrixAccumulator accumulator) { each(Matrices.asAccumulatorProcedure(accumulator)); return accumulator.accumulate(); } /** * Folds all elements of specified row in this matrix with given {@code accumulator}. * * @param i the row index * @param accumulator the vector accumulator * * @return the accumulated value */ public double foldRow(int i, VectorAccumulator accumulator) { eachInRow(i, Vectors.asAccumulatorProcedure(accumulator)); return accumulator.accumulate(); } /** * Folds all elements (in row-by-row manner) of this matrix with given {@code accumulator}. * * @param accumulator the vector accumulator * * @return the accumulated double array */ public double[] foldRows(VectorAccumulator accumulator) { double[] result = new double[rows]; for (int i = 0; i < rows; i++) { result[i] = foldRow(i, accumulator); } return result; } /** * Folds all elements of specified column in this matrix with given {@code accumulator}. * * @param j the column index * @param accumulator the vector accumulator * * @return the accumulated value */ public double foldColumn(int j, VectorAccumulator accumulator) { eachInColumn(j, Vectors.asAccumulatorProcedure(accumulator)); return accumulator.accumulate(); } /** * Folds all elements (in a column-by-column manner) of this matrix with given {@code accumulator}. * * @param accumulator the vector accumulator * * @return the accumulated double array */ public double[] foldColumns(VectorAccumulator accumulator) { double[] result = new double[columns]; for (int i = 0; i < columns; i++) { result[i] = foldColumn(i, accumulator); } return result; } /** * Checks whether this matrix compiles with given {@code predicate} or not. * * @param predicate the matrix predicate * * @return whether this matrix compiles with predicate */ public boolean is(MatrixPredicate predicate) { MatrixIterator it = iterator(); boolean result = predicate.test(rows, columns); while (it.hasNext() && result) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result = predicate.test(i, j, x); } return result; } /** * Checks whether this matrix compiles with given {@code predicate} or not. * * @param predicate the advanced matrix predicate * * @return whether this matrix compiles with predicate */ public boolean is(AdvancedMatrixPredicate predicate) { return predicate.test(this); } /** * Checks whether this matrix compiles with given {@code predicate} or not. * * @param predicate the matrix predicate * * @return whether this matrix compiles with predicate */ public boolean non(MatrixPredicate predicate) { return !is(predicate); } /** * Checks whether this matrix compiles with given {@code predicate} or not. * * @param predicate the advanced matrix predicate * * @return whether this matrix compiles with predicate */ public boolean non(AdvancedMatrixPredicate predicate) { return !is(predicate); } /** * Converts this matrix into the row vector. * * @return the row vector of this matrix */ public Vector toRowVector() { return getRow(0); } /** * Converts this matrix into the column vector. * * @return the column vector of this matrix */ public Vector toColumnVector() { return getColumn(0); } /** * Creates a new solver by given {@code factory} of this matrix. * * @param factory the solver factory * * @return the linear system solver of this matrix */ public LinearSystemSolver withSolver(LinearAlgebra.SolverFactory factory) { return factory.create(this); } /** * Creates a new inverter by given {@code factory} of this matrix. * * @param factory the inverter factory * * @return the inverter of this matrix */ public MatrixInverter withInverter(LinearAlgebra.InverterFactory factory) { return factory.create(this); } /** * Creates a new decompositor by given {@code factory} of this matrix. * * @param factory the decompositor factory * * @return the decompositor of this matrix */ public MatrixDecompositor withDecompositor(LinearAlgebra.DecompositorFactory factory) { return factory.create(this); } /** * Returns true when matrix is equal to given {@code matrix} with given {@code precision} * * @param matrix matrix * @param precision given precision * * @return equals of this matrix to that */ public boolean equals(Matrix matrix, double precision) { if (rows != matrix.rows() || columns != matrix.columns()) { return false; } boolean result = true; for (int i = 0; result && i < rows; i++) { for (int j = 0; result && j < columns; j++) { double a = get(i, j); double b = matrix.get(i, j); double diff = Math.abs(a - b); result = (a == b) || (diff < precision || diff / Math.max(Math.abs(a), Math.abs(b)) < precision); } } return result; } /** * Converts this matrix into the string representation. * * @param formatter the number formatter * * @return the matrix converted to a string */ public String mkString(NumberFormat formatter) { return mkString(formatter, DEFAULT_ROWS_DELIMITER, DEFAULT_COLUMNS_DELIMITER); } /** * Converts this matrix into the string representation. * * @param rowsDelimiter the rows' delimiter * @param columnsDelimiter the columns' delimiter * * @return the matrix converted to a string */ public String mkString(String rowsDelimiter, String columnsDelimiter) { return mkString(DEFAULT_FORMATTER, rowsDelimiter, columnsDelimiter); } /** * Converts this matrix into the string representation. * * @param formatter the number formatter * @param rowsDelimiter the rows' delimiter * @param columnsDelimiter the columns' delimiter * * @return the matrix converted to a string */ public String mkString(NumberFormat formatter, String rowsDelimiter, String columnsDelimiter) { // TODO: rewrite using iterators int formats[] = new int[columns]; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { double value = get(i, j); String output = formatter.format(value); int size = output.length(); formats[j] = size > formats[j] ? size : formats[j]; } } StringBuilder sb = new StringBuilder(); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { String output = formatter.format(get(i, j)); int outputLength = output.length(); if (outputLength < formats[j]) { int align = formats[j] - outputLength; if (align > INDENTS.length - 1) { indent(sb, align); } else { sb.append(INDENTS[align - 1]); } } sb.append(output) .append(j < columns - 1 ? columnsDelimiter : ""); } sb.append(rowsDelimiter); } return sb.toString(); } @Override public String toString() { return mkString(DEFAULT_FORMATTER, DEFAULT_ROWS_DELIMITER, DEFAULT_COLUMNS_DELIMITER); } /** * Returns a matrix iterator. * * @return a matrix iterator */ @Override public MatrixIterator iterator() { return rowMajorIterator(); } /** * Returns a row-major matrix iterator. * * @return a row-major matrix iterator. */ public RowMajorMatrixIterator rowMajorIterator() { return new RowMajorMatrixIterator(rows, columns) { private long limit = (long) rows * columns; private int i = - 1; @Override public int rowIndex() { return i / columns; } @Override public int columnIndex() { return i - rowIndex() * columns; } @Override public double get() { return Matrix.this.get(rowIndex(), columnIndex()); } @Override public void set(double value) { Matrix.this.set(rowIndex(), columnIndex(), value); } @Override public boolean hasNext() { return i + 1 < limit; } @Override public Double next() { i++; return get(); } }; } /** * Returns a column-major matrix iterator. * * @return a column-major matrix iterator. */ public ColumnMajorMatrixIterator columnMajorIterator() { return new ColumnMajorMatrixIterator(rows, columns) { private long limit = (long) rows * columns; private int i = -1; @Override public int rowIndex() { return i - columnIndex() * rows; } @Override public int columnIndex() { return i / rows; } @Override public double get() { return Matrix.this.get(rowIndex(), columnIndex()); } @Override public void set(double value) { Matrix.this.set(rowIndex(), columnIndex(), value); } @Override public boolean hasNext() { return i + 1 < limit; } @Override public Double next() { i++; return get(); } }; } /** * Returns a vector iterator of the given row {code i}. * * @return a vector iterator */ public VectorIterator iteratorOfRow(int i) { final int ii = i; return new VectorIterator(columns) { private int j = -1; @Override public int index() { return j; } @Override public double get() { return Matrix.this.get(ii, j); } @Override public void set(double value) { Matrix.this.set(ii, j, value); } @Override public boolean hasNext() { return j + 1 < columns; } @Override public Double next() { j++; return get(); } }; } /** * Returns a vector iterator of the given column {code j}. * * @return a vector iterator */ public VectorIterator iteratorOfColumn(int j) { final int jj = j; return new VectorIterator(rows) { private int i = -1; @Override public int index() { return i; } @Override public double get() { return Matrix.this.get(i, jj); } @Override public void set(double value) { Matrix.this.set(i, jj, value); } @Override public boolean hasNext() { return i + 1 < rows; } @Override public Double next() { i++; return get(); } }; } @Override public int hashCode() { MatrixIterator it = iterator(); int result = 17; while (it.hasNext()) { long value = it.next().longValue(); result = 37 * result + (int) (value ^ (value >>> 32)); } return result; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null) { return false; } if (!(o instanceof Matrix)) { return false; } Matrix matrix = (Matrix) o; return equals(matrix, Matrices.EPS); } /** * Converts this matrix using the given {@code factory}. * * @param factory the factory that creates an output matrix * @param type of the result matrix * * @return converted matrix */ public T to(MatrixFactory factory) { T result = factory.apply(rows, columns); apply(LinearAlgebra.IN_PLACE_COPY_MATRIX_TO_MATRIX, result); return result; } /** * Converts this matrix into a sparse matrix. * * @return a sparse matrix */ public SparseMatrix toSparseMatrix() { return to(Matrices.SPARSE); } /** * Converts this matrix into a dense matrix. * * @return a dense matrix */ public DenseMatrix toDenseMatrix() { return to(Matrices.DENSE); } /** * Converts this matrix into a row-major sparse matrix. * * @return a row-major sparse matrix */ public RowMajorSparseMatrix toRowMajorSparseMatrix() { return to(Matrices.SPARSE_ROW_MAJOR); } /** * Converts this matrix into a column-major sparse matrix. * * @return a row-major sparse matrix */ public ColumnMajorSparseMatrix toColumnMajorSparseMatrix() { return to(Matrices.SPARSE_COLUMN_MAJOR); } /** * Converts this matrix into the CSV (Comma Separated Value) string. * * @return a CSV string representing this matrix */ public String toCSV() { return toCSV(DEFAULT_FORMATTER); } /** * Converts this matrix into the Matrix Market string. * * @return a string in Matrix Market format representing this matrix; */ public String toMatrixMarket() { return toMatrixMarket(DEFAULT_FORMATTER); } /** * Converts this matrix into the CSV (Comma Separated Value) string * using the given {@code formatter}. * * @param formatter the number formatter * * @return a CSV string representing this matrix */ public String toCSV(NumberFormat formatter) { return mkString(formatter, "\n", ", "); } protected void ensureDimensionsAreCorrect(int rows, int columns) { if (rows < 0 || columns < 0) { fail("Wrong matrix dimensions: " + rows + "x" + columns); } if (rows == Integer.MAX_VALUE || columns == Integer.MAX_VALUE) { fail("Wrong matrix dimensions: use 'Integer.MAX_VALUE - 1' instead."); } } protected void ensureIndexesAreInBounds(int i, int j) { if (i < 0 || i >= rows) { throw new IndexOutOfBoundsException("Row '" + i + "' is invalid."); } if (j < 0 || j >= columns) { throw new IndexOutOfBoundsException("Column '" + j + "' is invalid."); } } protected void fail(String message) { throw new IllegalArgumentException(message); } private void indent(StringBuilder sb, int howMany) { while (howMany > 0) { sb.append(" "); howMany--; } } } la4j-0.6.0/src/main/java/org/la4j/Vector.java000066400000000000000000000642611263320764000205450ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Daniel Renshaw * Jakob Moellers * Maxim Samoylov * Miron Aseev * Ewald Grusk * */ package org.la4j; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Collection; import java.util.Map; import java.util.Random; import java.util.StringTokenizer; import org.la4j.iterator.VectorIterator; import org.la4j.vector.VectorFactory; import org.la4j.vector.DenseVector; import org.la4j.vector.functor.VectorAccumulator; import org.la4j.vector.functor.VectorFunction; import org.la4j.vector.functor.VectorPredicate; import org.la4j.vector.functor.VectorProcedure; import org.la4j.operation.VectorMatrixOperation; import org.la4j.operation.VectorOperation; import org.la4j.operation.VectorVectorOperation; import org.la4j.vector.SparseVector; /** * A vector represents an array of elements. It can be re-sized. */ public abstract class Vector implements Iterable { private static final String DEFAULT_DELIMITER = " "; private static final NumberFormat DEFAULT_FORMATTER = new DecimalFormat("0.000"); /** * Creates a zero {@link Vector} of the given {@code length}. */ public static Vector zero(int length) { return length > 1000 ? SparseVector.zero(length) : DenseVector.zero(length); } /** * Creates a constant {@link Vector} of the given {@code length} with * the given {@code value}. */ public static Vector constant(int length, double value) { return DenseVector.constant(length, value); } /** * Creates an unit {@link Vector} of the given {@code length}. */ public static Vector unit(int length) { return DenseVector.constant(length, 1.0); } /** * Creates a random {@link Vector} of the given {@code length} with * the given {@code Random}. */ public static Vector random(int length, Random random) { return DenseVector.random(length, random); } /** * Creates a new {@link Vector} from the given {@code array} w/o * copying the underlying array. */ public static Vector fromArray(double[] array) { return DenseVector.fromArray(array); } /** * Parses {@link Vector} from the given CSV string. * * @param csv the CSV string representing a vector * * @return a parsed vector */ public static Vector fromCSV(String csv) { StringTokenizer tokenizer = new StringTokenizer(csv, ", "); int estimatedLength = csv.length() / (5 + 2) + 1; // 5 symbols per element "0.000" // 2 symbols for delimiter ", " Vector result = DenseVector.zero(estimatedLength); int i = 0; while (tokenizer.hasMoreTokens()) { if (result.length() == i) { result = result.copyOfLength((i * 3) / 2 + 1); } double x = Double.valueOf(tokenizer.nextToken()); result.set(i++, x); } return result.copyOfLength(i); } /** * Parses {@link Vector} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed vector */ public static Vector fromMatrixMarket(String mm) { StringTokenizer body = new StringTokenizer(mm); if (!"%%MatrixMarket".equals(body.nextToken())) { throw new IllegalArgumentException("Wrong input file format: can not read header '%%MatrixMarket'."); } String object = body.nextToken(); if (!"vector".equals(object)) { throw new IllegalArgumentException("Unexpected object: " + object + "."); } String format = body.nextToken(); if (!"coordinate".equals(format) && !"array".equals(format)) { throw new IllegalArgumentException("Unknown format: " + format + "."); } String field = body.nextToken(); if (!"real".equals(field)) { throw new IllegalArgumentException("Unknown field type: " + field + "."); } int length = Integer.valueOf(body.nextToken()); if ("coordinate".equals(format)) { int cardinality = Integer.valueOf(body.nextToken()); Vector result = SparseVector.zero(length, cardinality); for (int k = 0; k < cardinality; k++) { int i = Integer.valueOf(body.nextToken()); double x = Double.valueOf(body.nextToken()); result.set(i - 1, x); } return result; } else { Vector result = DenseVector.zero(length); for (int i = 0; i < length; i++) { result.set(i, Double.valueOf(body.nextToken())); } return result; } } /** * Creates new {@link org.la4j.vector.dense.BasicVector} from {@code list} */ public static Vector fromCollection(Collection list) { return DenseVector.fromCollection(list); } /** * Creates new {@link org.la4j.vector.SparseVector} from {@code list} */ public static Vector fromMap(Map map, int length) { return SparseVector.fromMap(map, length); } /** * Length of this vector. */ protected int length; /** * Creates a vector of zero length. */ public Vector() { this(0); } /** * Creates a vector of given {@code length}. * * @param length the length of the vector */ public Vector(int length) { ensureLengthIsCorrect(length); this.length = length; } // // ============ ABSTRACT METHODS ============ // /** * Gets the specified element of this vector. * * @param i element's index * @return the element of this vector */ public abstract double get(int i); /** * Sets the specified element of this matrix to given {@code value}. * * @param i element's index * @param value element's new value */ public abstract void set(int i, double value); /** * Creates a blank (an empty vector) copy of this vector with the given * {@code length}. * * @param length the length of the blank vector * * @return blank vector */ public abstract Vector blankOfLength(int length); /** * Copies this vector into the new vector with specified {@code length}. * * @param length the length of new vector * * @return the copy of this vector with new length */ public abstract Vector copyOfLength(int length); /** * Converts this vector to matrix with only one row. * * @return the row matrix */ public abstract Matrix toRowMatrix(); /** * Converts this vector to matrix with only one column. * * @return the column matrix */ public abstract Matrix toColumnMatrix(); /** * Converts this vector to a diagonal matrix. * * @return a diagonal matrix */ public abstract Matrix toDiagonalMatrix(); /** * Pipes this vector to a given {@code operation}. * * @param operation the vector operation * (an operation that take vector and returns {@code T}) * @param the result type * * @return the result of an operation applied to this vector */ public abstract T apply(VectorOperation operation); /** * Pipes this vector to a given {@code operation}. * * @param operation the vector-vector operation * (an operation that takes two vectors and returns {@code T}) * @param the result type * @param that the right hand vector for the given operation * * @return the result of an operation applied to this and {@code that} vector */ public abstract T apply(VectorVectorOperation operation, Vector that); /** * Pipes this vector to a given {@code operation}. * * @param operation the vector-matrix operation * (an operation that takes vector and matrix and returns {@code T}) * @param the result type * @param that the right hand matrix for the given operation * * @return the result of an operation applied to this vector and {@code that} matrix */ public abstract T apply(VectorMatrixOperation operation, Matrix that); /** * Encodes this vector into a byte array. * * @return a byte array representing this vector */ public abstract byte[] toBinary(); /** * Converts this vector into the string in Matrix Market format * using the given {@code formatter}; * * @param formatter the number formater * * @return a Matrix Market string representing this vector */ public abstract String toMatrixMarket(NumberFormat formatter); // // ============ CONCRETE METHODS ============ // /** * Sets all elements of this vector to given {@code value}. * * @param value the element's new value */ public void setAll(double value) { VectorIterator it = iterator(); while (it.hasNext()) { it.next(); it.set(value); } } /** * Returns the length of this vector. * * @return length of this vector */ public int length() { return length; } /** * Adds given {@code value} (v) to this vector (X). * * @param value the right hand value for addition * * @return X + v */ public Vector add(double value) { VectorIterator it = iterator(); Vector result = blank(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, x + value); } return result; } /** * Adds given {@code vector} (X) to this vector (Y). * * @param that the right hand vector for addition * * @return X + Y */ public Vector add(Vector that) { return apply(LinearAlgebra.OO_PLACE_VECTORS_ADDITION, that); } /** * Multiplies this vector (X) by given {@code value} (v). * * @param value the right hand value for multiplication * * @return X * v */ public Vector multiply(double value) { VectorIterator it = iterator(); Vector result = blank(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, x * value); } return result; } /** * Calculates the Hadamard (element-wise) product of this vector and given {@code that}. * * @param that the right hand vector for Hadamard product * * @return the Hadamard product of two vectors */ public Vector hadamardProduct(Vector that) { return apply(LinearAlgebra.OO_PLACE_VECTOR_HADAMARD_PRODUCT, that); } /** * Multiples this vector (X) by given {@code that} (A). * * @param that the right hand matrix for multiplication * * @return X * A */ public Vector multiply(Matrix that) { return apply(LinearAlgebra.OO_PLACE_VECTOR_BY_MATRIX_MULTIPLICATION, that); } /** * Subtracts given {@code value} (v) from this vector (X). * * @param value the right hand value for subtraction * * @return X - v */ public Vector subtract(double value) { return add(-value); } /** * Subtracts given {@code that} (Y) from this vector (X). * * @param that the right hand vector for subtraction * * @return X - Y */ public Vector subtract(Vector that) { return apply(LinearAlgebra.OO_PLACE_VECTORS_SUBTRACTION, that); } /** * Divides this vector (X) by given {@code value} (v). * * @param value the right hand value for division * * @return X / v */ public Vector divide(double value) { return multiply(1.0 / value); } /** * Multiplies up all elements of this vector. * * @return product of all elements of this vector */ public double product() { return fold(Vectors.asProductAccumulator(1.0)); } /** * Summarizes all elements of the vector * * @return sum of all elements of the vector */ public double sum() { return fold(Vectors.asSumAccumulator(0.0)); } /** * Calculates the inner product of this vector and given {@code that}. * * @param that the right hand vector for inner product * * @return the inner product of two vectors */ public double innerProduct(Vector that) { return apply(LinearAlgebra.OO_PLACE_INNER_PRODUCT, that); } /** * Calculates the outer product of this vector and given {@code that}. * * @param that the the right hand vector for outer product * * @return the outer product of two vectors */ public Matrix outerProduct(Vector that) { return apply(LinearAlgebra.OO_PLACE_OUTER_PRODUCT, that); } /** * Calculates an Euclidean norm of this vector. * * @return an Euclidean norm */ public double norm() { return euclideanNorm(); } /** * Calculates an Euclidean norm of this vector. * * @return an Euclidean norm */ public double euclideanNorm() { return fold(Vectors.mkEuclideanNormAccumulator()); } /** * Calculates a Manhattan norm of this vector. * * @return a Manhattan norm */ public double manhattanNorm() { return fold(Vectors.mkManhattanNormAccumulator()); } /** * Calculates an Infinity norm of this vector. * * @return an Infinity norm */ public double infinityNorm() { return fold(Vectors.mkInfinityNormAccumulator()); } /** * Swaps the specified elements of this vector. * * @param i element's index * @param j element's index */ public void swapElements(int i, int j) { if (i != j) { double s = get(i); set(i, get(j)); set(j, s); } } /** * Creates a blank (an empty vector with same length) copy of this vector. * * @return blank vector */ public Vector blank() { return blankOfLength(length); } /** * Copies this vector. * * @return the copy of this vector */ public Vector copy() { return copyOfLength(length); } /** * Shuffles this vector. * *

* Copies this vector in the new vector that contains the same elements but with * the elements shuffled around (which might also result in the same vector * (all outcomes are equally probable)). *

* * @return the shuffled vector */ public Vector shuffle() { Vector result = copy(); // Conduct Fisher-Yates shuffle Random random = new Random(); for (int i = 0; i < length; i++) { int j = random.nextInt(length - i) + i; swapElements(i, j); } return result; } /** * Retrieves the specified sub-vector of this vector. The sub-vector is specified by * interval of indices. * * @param from the beginning of indices interval * @param until the ending of indices interval * * @return the sub-vector of this vector */ public Vector slice(int from, int until) { if (until - from < 0) { fail("Wrong slice range: [" + from + ".." + until + "]."); } Vector result = blankOfLength(until - from); for (int i = from; i < until; i++) { result.set(i - from, get(i)); } return result; } /** * Retrieves the specified sub-vector of this vector. The sub-vector is specified by * interval of indices. The left point of interval is fixed to zero. * * @param until the ending of indices interval * * @return the sub-vector of this vector */ public Vector sliceLeft(int until) { return slice(0, until); } /** * Retrieves the specified sub-vector of this vector. The sub-vector is specified by * interval of indices. The right point of interval is fixed to vector's length. * * @param from the beginning of indices interval * * @return the sub-vector of this vector */ public Vector sliceRight(int from) { return slice(from, length); } /** * Returns a new vector with the selected elements. * * @param indices the array of indices * * @return the new vector with the selected elements */ public Vector select(int[] indices) { int newLength = indices.length; if (newLength == 0) { fail("No elements selected."); } Vector result = blankOfLength(newLength); for (int i = 0; i < newLength; i++) { result.set(i, get(indices[i])); } return result; } /** * Applies given {@code procedure} to each element of this vector. * * @param procedure the vector procedure */ public void each(VectorProcedure procedure) { VectorIterator it = iterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); procedure.apply(i, x); } } /** * Searches for the maximum value of the elements of this vector. * * @return the maximum value of this vector */ public double max() { return fold(Vectors.mkMaxAccumulator()); } /** * Searches for the minimum value of the elements of this vector. * * @return the minimum value of this vector */ public double min() { return fold(Vectors.mkMinAccumulator()); } /** * Builds a new vector by applying given {@code function} to each element * of this vector. * * @param function the vector function * * @return the transformed vector */ public Vector transform(VectorFunction function) { VectorIterator it = iterator(); Vector result = blank(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, function.evaluate(i, x)); } return result; } /** * Updates all elements of this vector by applying given {@code function}. * * @param function the the vector function */ public void update(VectorFunction function) { VectorIterator it = iterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); it.set(function.evaluate(i, x)); } } /** * Updates the specified element of this vector by applying given {@code function}. * * @param i element's index * @param function the vector function */ public void updateAt(int i, VectorFunction function) { set(i, function.evaluate(i, get(i))); } /** * Folds all elements of this vector with given {@code accumulator}. * * @param accumulator the vector accumulator * * @return the accumulated value */ public double fold(VectorAccumulator accumulator) { each(Vectors.asAccumulatorProcedure(accumulator)); return accumulator.accumulate(); } /** * Checks whether this vector compiles with given {@code predicate} or not. * * @param predicate the vector predicate * * @return whether this vector compiles with predicate */ public boolean is(VectorPredicate predicate) { boolean result = true; VectorIterator it = iterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result = result && predicate.test(i, x); } return result; } /** * Checks whether this vector compiles with given {@code predicate} or not. * * @param predicate the vector predicate * * @return whether this vector compiles with predicate */ public boolean non(VectorPredicate predicate) { return !is(predicate); } /** * Returns true when vector is equal to given {@code that} vector with given * {@code precision}. * * @param that vector * @param precision given precision * * @return equals of this matrix to that */ public boolean equals(Vector that, double precision) { if (this == that) { return true; } if (this.length != that.length()) { return false; } boolean result = true; for (int i = 0; result && i < length; i++) { double a = get(i); double b = that.get(i); double diff = Math.abs(a - b); result = (a == b) || (diff < precision || diff / Math.max(Math.abs(a), Math.abs(b)) < precision); } return result; } /** * Converts this vector into the string representation. * * @param formatter the number formatter * * @return the vector converted to a string */ public String mkString(NumberFormat formatter) { return mkString(formatter, DEFAULT_DELIMITER); } /** * Converts this vector into the string representation. * * @param formatter the number formatter * @param delimiter the element's delimiter * * @return the vector converted to a string */ public String mkString(NumberFormat formatter, String delimiter) { StringBuilder sb = new StringBuilder(); VectorIterator it = iterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); sb.append(formatter.format(x)) .append((i < length - 1 ? delimiter : "")); } return sb.toString(); } /** * Converts this vector into a string representation. * * @return a string representation of this vector */ @Override public String toString() { return mkString(DEFAULT_FORMATTER, DEFAULT_DELIMITER); } /** * Checks where this vector is equal to the given object {@code o}. */ @Override public boolean equals(Object o) { return o != null && (o instanceof Vector) && equals((Vector) o, Vectors.EPS); } /** * Calculates the hash-code of this vector. */ @Override public int hashCode() { VectorIterator it = iterator(); int result = 17; while (it.hasNext()) { long value = it.next().longValue(); result = 37 * result + (int) (value ^ (value >>> 32)); } return result; } /** * Returns a vector iterator. * * @return a vector iterator. */ @Override public VectorIterator iterator() { return new VectorIterator(length) { private int i = -1; @Override public int index() { return i; } @Override public double get() { return Vector.this.get(i); } @Override public void set(double value) { Vector.this.set(i, value); } @Override public boolean hasNext() { return i + 1 < length; } @Override public Double next() { i++; return get(); } }; } /** * Converts this vector using the given {@code factory}. * * @param factory the factory that creates an output vector * @param type of the result vector * * @return a converted vector */ public T to(VectorFactory factory) { VectorIterator it = iterator(); T result = factory.apply(length); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, x); } return result; } /** * Converts this vector into a {@link org.la4j.vector.DenseVector}. * * @return a dense vector */ public DenseVector toDenseVector() { return to(Vectors.DENSE); } /** * Converts this vector into a {@link org.la4j.vector.SparseVector}. * * @return a sparse vector */ public SparseVector toSparseVector() { return to(Vectors.SPARSE); } /** * Converts this vector into the CSV (Comma Separated Value) string. * * @return a CSV string representing this vector */ public String toCSV() { return toCSV(DEFAULT_FORMATTER); } /** * Converts this vector into the CSV (Comma Separated Value) string * using the given {@code formatter}. * * @return a CSV string representing this vector */ public String toCSV(NumberFormat formatter) { return mkString(formatter, ", "); } /** * Converts this vector into the string in Matrix Market format. * * @return a Matrix Market string representing this vector */ public String toMatrixMarket() { return toMatrixMarket(DEFAULT_FORMATTER); } protected void ensureLengthIsCorrect(int length) { if (length < 0) { fail("Wrong vector length: " + length); } if (length == Integer.MAX_VALUE) { fail("Wrong vector length: use 'Integer.MAX_VALUE - 1' instead."); } } protected void fail(String message) { throw new IllegalArgumentException(message); } } la4j-0.6.0/src/main/java/org/la4j/Vectors.java000066400000000000000000000343551263320764000207310ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Maxim Samoylov * Miron Aseev * */ package org.la4j; import java.math.BigDecimal; import java.math.RoundingMode; import org.la4j.vector.VectorFactory; import org.la4j.vector.dense.BasicVector; import org.la4j.vector.functor.VectorAccumulator; import org.la4j.vector.functor.VectorFunction; import org.la4j.vector.functor.VectorPredicate; import org.la4j.vector.functor.VectorProcedure; import org.la4j.vector.sparse.CompressedVector; public final class Vectors { public static final double EPS = LinearAlgebra.EPS; public static final int ROUND_FACTOR = LinearAlgebra.ROUND_FACTOR; public static final VectorFactory BASIC = new VectorFactory() { @Override public BasicVector apply(int length) { return BasicVector.zero(length); } }; public static final VectorFactory COMPRESSED = new VectorFactory() { @Override public CompressedVector apply(int length) { return CompressedVector.zero(length); } }; public static final VectorFactory[] FACTORIES = { BASIC, COMPRESSED }; public static final VectorFactory DENSE = BASIC; public static final VectorFactory SPARSE = COMPRESSED; /** * Checks whether the vector is a * zero * vector. */ public static final VectorPredicate ZERO_VECTOR = new VectorPredicate() { @Override public boolean test(int i, double value) { return Math.abs(value) < EPS; } }; /** * Checks whether the vector is a * positive * vector. */ public static final VectorPredicate POSITIVE_VECTOR = new VectorPredicate() { @Override public boolean test(int i, double value) { return value > 0.0; } }; /** * Checks whether the vector is a * negative * vector. */ public static final VectorPredicate NEGATIVE_VECTOR = new VectorPredicate() { @Override public boolean test(int i, double value) { return value < 0.0; } }; /** * Increases each element of vector by 1. */ public static final VectorFunction INC_FUNCTION = new VectorFunction() { @Override public double evaluate(int i, double value) { return value + 1.0; } }; /** * Decreases each element of vectors by 1. */ public static final VectorFunction DEC_FUNCTION = new VectorFunction() { @Override public double evaluate(int i, double value) { return value - 1.0; } }; /** * Inverts each element of vector. */ public static final VectorFunction INV_FUNCTION = new VectorFunction() { @Override public double evaluate(int i, double value) { return -value; } }; /** * Creates a const function that evaluates it's argument to given {@code value}. * * @param arg a const value * * @return a closure object that does {@code _} */ public static VectorFunction asConstFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return arg; } }; } /** * Creates a plus function that adds given {@code value} to it's argument. * * @param arg a value to be added to function's argument * * @return a closure object that does {@code _ + _} */ public static VectorFunction asPlusFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value + arg; } }; } /** * Creates a minus function that subtracts given {@code value} from it's argument. * * @param arg a value to be subtracted from function's argument * * @return a closure that does {@code _ - _} */ public static VectorFunction asMinusFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value - arg; } }; } /** * Creates a mul function that multiplies given {@code value} by it's argument. * * @param arg a value to be multiplied by function's argument * * @return a closure that does {@code _ * _} */ public static VectorFunction asMulFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value * arg; } }; } /** * Creates a div function that divides it's argument by given {@code value}. * * @param arg a divisor value * * @return a closure that does {@code _ / _} */ public static VectorFunction asDivFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value / arg; } }; } /** * Creates a mod function that calculates the modulus of it's argument and given {@code value}. * * @param arg a divisor value * * @return a closure that does {@code _ % _} */ public static VectorFunction asModFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value % arg; } }; } /** * Creates a sum vector accumulator that calculates the sum of all elements in the vector. * * @param neutral the neutral value * * @return a sum accumulator */ public static VectorAccumulator asSumAccumulator(final double neutral) { return new VectorAccumulator() { private BigDecimal result = new BigDecimal(neutral); @Override public void update(int i, double value) { result = result.add(new BigDecimal(value)); } @Override public double accumulate() { double value = result.setScale(Vectors.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = new BigDecimal(neutral); return value; } }; } /** * Creates a product vector accumulator that calculates the product of all elements in the vector. * * @param neutral the neutral value * * @return a product accumulator */ public static VectorAccumulator asProductAccumulator(final double neutral) { return new VectorAccumulator() { private BigDecimal result = new BigDecimal(neutral); @Override public void update(int i, double value) { result = result.multiply(new BigDecimal(value)); } @Override public double accumulate() { double value = result.setScale(Vectors.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = new BigDecimal(neutral); return value; } }; } /** * Makes a minimum vector accumulator that accumulates the minimum across vector elements. * * @return a minimum vector accumulator */ public static VectorAccumulator mkMinAccumulator() { return new VectorAccumulator() { private double result = Double.POSITIVE_INFINITY; @Override public void update(int i, double value) { result = Math.min(result, value); } @Override public double accumulate() { double value = result; result = Double.POSITIVE_INFINITY; return value; } }; } /** * Makes a maximum vector accumulator that accumulates the maximum across vector elements. * * @return a maximum vector accumulator */ public static VectorAccumulator mkMaxAccumulator() { return new VectorAccumulator() { private double result = Double.NEGATIVE_INFINITY; @Override public void update(int i, double value) { result = Math.max(result, value); } @Override public double accumulate() { double value = result; result = Double.NEGATIVE_INFINITY; return value; } }; } /** * Makes an Euclidean norm accumulator that allows to use * {@link org.la4j.Vector#fold(org.la4j.vector.functor.VectorAccumulator)} method for norm calculation. * * @return an Euclidean norm accumulator */ public static VectorAccumulator mkEuclideanNormAccumulator() { return new VectorAccumulator() { private BigDecimal result = new BigDecimal(0.0); @Override public void update(int i, double value) { result = result.add(new BigDecimal(value * value)); } @Override public double accumulate() { double value = result.setScale(Vectors.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = new BigDecimal(0.0); return Math.sqrt(value); } }; } /** * Makes a Manhattan norm accumulator that allows to use * {@link org.la4j.Vector#fold(org.la4j.vector.functor.VectorAccumulator)} method for norm calculation. * * @return a Manhattan norm accumulator */ public static VectorAccumulator mkManhattanNormAccumulator() { return new VectorAccumulator() { private double result = 0.0; @Override public void update(int i, double value) { result += Math.abs(value); } @Override public double accumulate() { double value = result; result = 0.0; return value; } }; } /** * Makes an Infinity norm accumulator that allows to use * {@link org.la4j.Vector#fold(org.la4j.vector.functor.VectorAccumulator)} method for norm calculation. * * @return an Infinity norm accumulator */ public static VectorAccumulator mkInfinityNormAccumulator() { return new VectorAccumulator() { private double result = Double.NEGATIVE_INFINITY; @Override public void update(int i, double value) { result = Math.max(result, Math.abs(value)); } @Override public double accumulate() { double value = result; result = Double.NEGATIVE_INFINITY; return value; } }; } /** * Creates a sum function accumulator, that calculates the sum of all * elements in the vector after applying given {@code function} to each of them. * * @param neutral the neutral value * @param function the vector function * * @return a sum function accumulator */ public static VectorAccumulator asSumFunctionAccumulator(final double neutral, final VectorFunction function) { return new VectorAccumulator() { private final VectorAccumulator sumAccumulator = Vectors.asSumAccumulator(neutral); @Override public void update(int i, double value) { sumAccumulator.update(i, function.evaluate(i, value)); } @Override public double accumulate() { return sumAccumulator.accumulate(); } }; } /** * Creates a product function accumulator, that calculates the product of * all elements in the vector after applying given {@code function} to * each of them. * * @param neutral the neutral value * @param function the vector function * * @return a product function accumulator */ public static VectorAccumulator asProductFunctionAccumulator(final double neutral, final VectorFunction function) { return new VectorAccumulator() { private final VectorAccumulator productAccumulator = Vectors.asProductAccumulator(neutral); @Override public void update(int i, double value) { productAccumulator.update(i, function.evaluate(i, value)); } @Override public double accumulate() { return productAccumulator.accumulate(); } }; } /** * Creates an accumulator procedure that adapts a vector accumulator for procedure * interface. This is useful for reusing a single accumulator for multiple fold operations * in multiple vectors. * * @param accumulator the vector accumulator * * @return an accumulator procedure */ public static VectorProcedure asAccumulatorProcedure(final VectorAccumulator accumulator) { return new VectorProcedure() { @Override public void apply(int i, double value) { accumulator.update(i, value); } }; } } la4j-0.6.0/src/main/java/org/la4j/decomposition/000077500000000000000000000000001263320764000213035ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/decomposition/AbstractDecompositor.java000066400000000000000000000023561263320764000263070ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.la4j.Matrix; public abstract class AbstractDecompositor implements MatrixDecompositor { protected Matrix matrix; public AbstractDecompositor(Matrix matrix) { if (!applicableTo(matrix)) { fail("Given matrix can not be used with this decompositor."); } this.matrix = matrix; } @Override public Matrix self() { return matrix; } protected void fail(String message) { throw new IllegalArgumentException(message); } } la4j-0.6.0/src/main/java/org/la4j/decomposition/CholeskyDecompositor.java000066400000000000000000000046471263320764000263320ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Miron Aseev * */ package org.la4j.decomposition; import org.la4j.Matrices; import org.la4j.Matrix; /** * This class represents Cholesky decomposition of matrices. More details *

* here *

*/ public class CholeskyDecompositor extends AbstractDecompositor implements MatrixDecompositor { public CholeskyDecompositor(Matrix matrix) { super(matrix); } /** * Returns the result of Cholesky decomposition of given matrix *

* See * http://mathworld.wolfram.com/CholeskyDecomposition.html for more * details. *

* * @return { L } */ @Override public Matrix[] decompose() { Matrix l = matrix.blankOfShape(matrix.rows(), matrix.rows()); for (int j = 0; j < l.rows(); j++) { double d = 0.0; for (int k = 0; k < j; k++) { double s = 0.0; for (int i = 0; i < k; i++) { s += l.get(k, i) * l.get(j, i); } s = (matrix.get(j, k) - s) / l.get(k, k); l.set(j, k, s); d = d + s * s; } d = matrix.get(j, j) - d; l.set(j, j, Math.sqrt(Math.max(d, 0.0))); for (int k = j + 1; k < l.rows(); k++) { l.set(j, k, 0.0); } } return new Matrix[] { l }; } @Override public boolean applicableTo(Matrix matrix) { return matrix.rows() == matrix.columns() && matrix.is(Matrices.SYMMETRIC_MATRIX) && matrix.is(Matrices.POSITIVE_DEFINITE_MATRIX); } } la4j-0.6.0/src/main/java/org/la4j/decomposition/EigenDecompositor.java000066400000000000000000000657061263320764000256030ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Maxim Samoylov * */ package org.la4j.decomposition; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.SparseMatrix; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.vector.DenseVector; import org.la4j.vector.functor.VectorAccumulator; /** * This class represents Eigen decomposition of matrices. More details *

* here. *

*/ public class EigenDecompositor extends AbstractDecompositor implements MatrixDecompositor { public EigenDecompositor(Matrix matrix) { super(matrix); } /** * Returns the result of Eigen (EVD) decomposition of given matrix *

* See * http://mathworld.wolfram.com/EigenDecomposition.html for more * details. *

* * @return { V, D } */ @Override public Matrix[] decompose() { if (matrix.is(Matrices.SYMMETRIC_MATRIX)) { return decomposeSymmetricMatrix(matrix); } else if (matrix.rows() == matrix.columns()) { return decomposeNonSymmetricMatrix(matrix); } else { throw new IllegalArgumentException("Can't decompose rectangle matrix"); } } @Override public boolean applicableTo(Matrix matrix) { return matrix.rows() == matrix.columns(); } /** * Returns the result of Eigen decomposition for symmetric * matrix *

* See * http://mathworld.wolfram.com/EigenDecomposition.html for more * details. *

* * @param matrix * @return { V, D } */ private Matrix[] decomposeSymmetricMatrix(Matrix matrix) { Matrix d = matrix.copy(); Matrix v = SparseMatrix.identity(matrix.rows()); Vector r = generateR(d); Matrix u = SparseMatrix.identity(matrix.rows()); VectorAccumulator normAccumulator = Vectors.mkEuclideanNormAccumulator(); double n = Matrices.EPS; double nn = r.fold(normAccumulator); int kk = 0, ll = 0; while (Math.abs(n - nn) > Matrices.EPS) { int k = findMax(r); int l = findMax(d, k); regenerateU(u, d, k, l, kk, ll); kk = k; ll = l; v = v.multiply(u); d = u.transpose().multiply(d.multiply(u)); r.set(k, generateRi(d, k)); r.set(l, generateRi(d, l)); n = nn; nn = r.fold(normAccumulator); } return new Matrix[] { v, d }; } private int findMax(Vector vector) { double value = vector.get(0); int result = 0; for (int i = 1; i < vector.length(); i++) { double v = vector.get(i); if (Math.abs(value) < Math.abs(v)) { result = i; value = v; } } return result; } private int findMax(Matrix matrix, int i) { double value = i > 0 ? matrix.get(i, 0) : matrix.get(i, 1); int result = i > 0 ? 0 : 1; for (int j = 0; j < matrix.columns(); j++) { if (i != j) { double v = matrix.get(i, j); if (Math.abs(value) < Math.abs(v)) { result = j; value = v; } } } return result; } private Vector generateR(Matrix matrix) { Vector result = DenseVector.zero(matrix.rows()); for (int i = 0; i < matrix.rows(); i++) { result.set(i, generateRi(matrix, i)); } return result; } private double generateRi(Matrix matrix, int i) { double acc = 0; for (int j = 0; j < matrix.columns(); j++) { if (j != i) { double value = matrix.get(i, j); acc += value * value; } } return acc; } private void regenerateU(Matrix u, Matrix matrix, int k, int l, int kk, int ll) { u.set(kk, kk, 1.0); u.set(ll, ll, 1.0); u.set(kk, ll, 0.0); u.set(ll, kk, 0.0); double alpha = 0.0, beta = 0.0; if (Math.abs(matrix.get(k, k) - matrix.get(l, l)) < Matrices.EPS) { alpha = beta = Math.sqrt(0.5); } else { double mu = 2 * matrix.get(k, l) / (matrix.get(k, k) - matrix.get(l, l)); mu = 1.0 / Math.sqrt(1.0 + mu * mu); alpha = Math.sqrt(0.5 * (1.0 + mu)); beta = Math.signum(mu) * Math.sqrt(0.5 * (1.0 - mu)); } u.set(k, k, alpha); u.set(l, l, alpha); u.set(k, l, -beta); u.set(l, k, beta); } /** * Returns the result of Eigen decomposition for non-symmetric * matrix *

* See * http://mathworld.wolfram.com/EigenDecomposition.html for more * details. *

* * @param matrix * @return { P, D } */ private Matrix[] decomposeNonSymmetricMatrix(Matrix matrix) { Matrix A = matrix.copy(); int n = matrix.columns(); Matrix v = SparseMatrix.identity(n); Vector d = DenseVector.zero(n); Vector e = DenseVector.zero(n); Matrix h = A.copy(); Vector ort = DenseVector.zero(n); // Reduce to Hessenberg form. orthes(h, v, ort); // Reduce Hessenberg to real Schur form. hqr2(h, v, d, e); Matrix dd = matrix.blankOfShape(n, n); for (int i = 0; i < n; i++) { dd.set(i, i, d.get(i)); if (e.get(i) > 0) { dd.set(i, i + 1, e.get(i)); } else if (e.get(i) < 0) { dd.set(i, i - 1, e.get(i)); } } return new Matrix[] { v, dd }; } // Nonsymmetric reduction to Hessenberg form. private void orthes(Matrix h, Matrix v, Vector ort) { // This is derived from the Algol procedures orthes and ortran, // by Martin and Wilkinson, Handbook for Auto. Comp., // Vol.ii-Linear Algebra, and the corresponding // Fortran subroutines in EISPACK. int n = ort.length(); int low = 0; int high = n - 1; for (int m = low + 1; m <= high - 1; m++) { // Scale column. double scale = 0.0; for (int i = m; i <= high; i++) { scale = scale + Math.abs(h.get(i, m - 1)); } if (scale != 0.0) { // Compute Householder transformation. double hh = 0.0; for (int i = high; i >= m; i--) { ort.set(i, h.get(i, m - 1) / scale); hh += ort.get(i) * ort.get(i); } double g = Math.sqrt(hh); if (ort.get(m) > Matrices.EPS) { g = -g; } hh = hh - ort.get(m) * g; ort.updateAt(m, Vectors.asMinusFunction(g)); // Apply Householder similarity transformation // H = (I-u*u'/h)*H*(I-u*u')/h) for (int j = m; j < n; j++) { double f = 0.0; for (int i = high; i >= m; i--) { f += ort.get(i) * h.get(i, j); } f = f / hh; for (int i = m; i <= high; i++) { h.updateAt(i, j, Matrices.asMinusFunction(f * ort.get(i))); } } for (int i = 0; i <= high; i++) { double f = 0.0; for (int j = high; j >= m; j--) { f += ort.get(j) * h.get(i, j); } f = f / hh; for (int j = m; j <= high; j++) { h.updateAt(i, j, Matrices.asMinusFunction(f * ort.get(j))); } } ort.set(m, scale * ort.get(m)); h.set(m, m - 1, scale * g); } } // Accumulate transformations (Algol's ortran). for (int m = high - 1; m >= low + 1; m--) { if (Math.abs(h.get(m, m - 1)) > Matrices.EPS) { for (int i = m + 1; i <= high; i++) { ort.set(i, h.get(i, m - 1)); } for (int j = m; j <= high; j++) { double g = 0.0; for (int i = m; i <= high; i++) { g += ort.get(i) * v.get(i, j); } // Double division avoids possible underflow g = (g / ort.get(m)) / h.get(m, m - 1); for (int i = m; i <= high; i++) { v.updateAt(i, j, Matrices.asPlusFunction(g * ort.get(i))); } } } } } // Nonsymmetric reduction from Hessenberg to real Schur form. private void hqr2(Matrix H, Matrix V, Vector d, Vector e) { // This is derived from the Algol procedure hqr2, // by Martin and Wilkinson, Handbook for Auto. Comp., // Vol.ii-Linear Algebra, and the corresponding // Fortran subroutine in EISPACK. // Initialize int nn = e.length(); int n = nn - 1; int low = 0; int high = nn - 1; double eps = Math.pow(2.0, -52.0); double exshift = 0.0; double p = 0, q = 0, r = 0, s = 0, z = 0, t, w, x, y; // Store roots isolated by balanc and compute matrix norm double norm = 0.0; for (int i = 0; i < nn; i++) { if (i < low | i > high) { d.set(i, H.get(i, i)); e.set(i, 0.0); } for (int j = Math.max(i - 1, 0); j < nn; j++) { norm = norm + Math.abs(H.get(i, j)); } } // Outer loop over eigenvalue index int iter = 0; while (n >= low) { // Look for single small sub-diagonal element int l = n; while (l > low) { s = Math.abs(H.get(l - 1, l - 1)) + Math.abs(H.get(l, l)); if (s == 0.0) { s = norm; } if (Math.abs(H.get(l, l - 1)) < eps * s) { break; } l--; } // Check for convergence // One root found if (l == n) { H.updateAt(n, n, Matrices.asPlusFunction(exshift)); d.set(n, H.get(n, n)); e.set(n, 0.0); n--; iter = 0; // Two roots found } else if (l == n - 1) { w = H.get(n, n - 1) * H.get(n - 1, n); p = (H.get(n - 1, n - 1) - H.get(n, n)) / 2.0; q = p * p + w; z = Math.sqrt(Math.abs(q)); H.updateAt(n, n, Matrices.asPlusFunction(exshift)); H.updateAt(n - 1, n - 1, Matrices.asPlusFunction(exshift)); x = H.get(n, n); // Real pair if (q >= 0) { if (p >= 0) { z = p + z; } else { z = p - z; } d.set(n - 1, x + z); d.set(n, d.get(n - 1)); if (z != 0.0) { d.set(n, x - w / z); } e.set(n - 1, 0.0); e.set(n, 0.0); x = H.get(n, n - 1); s = Math.abs(x) + Math.abs(z); p = x / s; q = z / s; r = Math.sqrt(p * p + q * q); p = p / r; q = q / r; // Row modification for (int j = n - 1; j < nn; j++) { z = H.get(n - 1, j); H.set(n - 1, j, q * z + p * H.get(n, j)); H.set(n, j, q * H.get(n, j) - p * z); } // Column modification for (int i = 0; i <= n; i++) { z = H.get(i, n - 1); H.set(i, n - 1, q * z + p * H.get(i, n)); H.set(i, n, q * H.get(i, n) - p * z); } // Accumulate transformations for (int i = low; i <= high; i++) { z = V.get(i, n - 1); V.set(i, n - 1, q * z + p * V.get(i, n)); V.set(i, n, q * V.get(i, n) - p * z); } // Complex pair } else { d.set(n - 1, x + p); d.set(n, x + p); e.set(n - 1, z); e.set(n, -z); } n = n - 2; iter = 0; // No convergence yet } else { // Form shift x = H.get(n, n); y = 0.0; w = 0.0; if (l < n) { y = H.get(n - 1, n - 1); w = H.get(n, n - 1) * H.get(n - 1, n); } // Wilkinson's original ad hoc shift if (iter == 10) { exshift += x; for (int i = low; i <= n; i++) { H.updateAt(i, i, Matrices.asMinusFunction(x)); } s = Math.abs(H.get(n, n - 1)) + Math.abs(H.get(n - 1, n - 2)); x = y = 0.75 * s; // WTF ??? w = -0.4375 * s * s; // Are you kidding me??? } // MATLAB's new ad hoc shift if (iter == 30) { s = (y - x) / 2.0; s = s * s + w; if (s > 0) { s = Math.sqrt(s); if (y < x) { s = -s; } s = x - w / ((y - x) / 2.0 + s); for (int i = low; i <= n; i++) { H.updateAt(i, i, Matrices.asMinusFunction(s)); } exshift += s; x = y = w = 0.964; } } iter = iter + 1; // (Could check iteration count here.) // Look for two consecutive small sub-diagonal elements int m = n - 2; while (m >= l) { z = H.get(m, m); r = x - z; s = y - z; p = (r * s - w) / H.get(m + 1, m) + H.get(m, m + 1); q = H.get(m + 1, m + 1) - z - r - s; r = H.get(m + 2, m + 1); s = Math.abs(p) + Math.abs(q) + Math.abs(r); p = p / s; q = q / s; r = r / s; if (m == l) { break; } if (Math.abs(H.get(m, m - 1)) * (Math.abs(q) + Math.abs(r)) < eps * (Math.abs(p) * (Math.abs(H.get(m - 1, m - 1)) + Math.abs(z) + Math.abs(H.get(m + 1, m + 1))))) { break; } m--; } for (int i = m + 2; i <= n; i++) { H.set(i, i - 2, 0.0); if (i > m + 2) { H.set(i, i - 3, 0.0); } } // Double QR step involving rows l:n and columns m:n for (int k = m; k <= n - 1; k++) { boolean notlast = (k != n - 1); if (k != m) { p = H.get(k, k - 1); q = H.get(k + 1, k - 1); r = (notlast ? H.get(k + 2, k - 1) : 0.0); x = Math.abs(p) + Math.abs(q) + Math.abs(r); if (x == 0.0) { continue; } p = p / x; q = q / x; r = r / x; } s = Math.sqrt(p * p + q * q + r * r); if (p < 0) { s = -s; } if (s != 0) { if (k != m) { H.set(k, k - 1, -s * x); } else if (l != m) { H.updateAt(k, k - 1, Matrices.INV_FUNCTION); } p = p + s; x = p / s; y = q / s; z = r / s; q = q / p; r = r / p; // Row modification for (int j = k; j < nn; j++) { p = H.get(k, j) + q * H.get(k + 1, j); if (notlast) { p = p + r * H.get(k + 2, j); H.updateAt(k + 2, j, Matrices.asMinusFunction(p * z)); } H.updateAt(k, j, Matrices.asMinusFunction(p * x)); H.updateAt(k + 1, j, Matrices.asMinusFunction(p * y)); } // Column modification for (int i = 0; i <= Math.min(n, k + 3); i++) { p = x * H.get(i, k) + y * H.get(i, k + 1); if (notlast) { p = p + z * H.get(i, k + 2); H.updateAt(i, k + 2, Matrices.asMinusFunction(p * r)); } H.updateAt(i, k, Matrices.asMinusFunction(p)); H.updateAt(i, k + 1, Matrices.asMinusFunction(p * q)); } // Accumulate transformations for (int i = low; i <= high; i++) { p = x * V.get(i, k) + y * V.get(i, k + 1); if (notlast) { p = p + z * V.get(i, k + 2); V.updateAt(i, k + 2, Matrices.asMinusFunction(p * r)); } V.updateAt(i, k, Matrices.asMinusFunction(p)); V.updateAt(i, k + 1, Matrices.asMinusFunction(p * q)); } } // (s != 0) } // k loop } // check convergence } // while (n >= low) // Backsubstitute to find vectors of upper triangular form if (norm == 0.0) { return; } for (n = nn - 1; n >= 0; n--) { p = d.get(n); q = e.get(n); // Real vector if (q == 0) { int l = n; H.set(n, n, 1.0); for (int i = n - 1; i >= 0; i--) { w = H.get(i, i) - p; r = 0.0; for (int j = l; j <= n; j++) { r = r + H.get(i, j) * H.get(j, n); } if (e.get(i) < 0.0) { z = w; s = r; } else { l = i; if (e.get(i) == 0.0) { if (w != 0.0) { H.set(i, n, -r / w); } else { H.set(i, n, -r / (eps * norm)); } // Solve real equations } else { x = H.get(i, i + 1); y = H.get(i + 1, i); q = (d.get(i) - p) * (d.get(i) - p) + e.get(i) * e.get(i); t = (x * s - z * r) / q; H.set(i, n, t); if (Math.abs(x) > Math.abs(z)) { H.set(i + 1, n, (-r - w * t) / x); } else { H.set(i + 1, n, (-s - y * t) / z); } } // Overflow control t = Math.abs(H.get(i, n)); if ((eps * t) * t > 1) { for (int j = i; j <= n; j++) { H.updateAt(j, n, Matrices.asDivFunction(t)); } } } } // Complex vector } else if (q < 0) { int l = n - 1; // Last vector component imaginary so matrix is triangular if (Math.abs(H.get(n, n - 1)) > Math.abs(H.get(n - 1, n))) { H.set(n - 1, n - 1, q / H.get(n, n - 1)); H.set(n - 1, n, -(H.get(n, n) - p) / H.get(n, n - 1)); } else { double cdiv[] = cdiv(0.0, -H.get(n - 1, n), H.get(n - 1, n - 1) - p, q); H.set(n - 1, n - 1, cdiv[0]); H.set(n - 1, n, cdiv[1]); } H.set(n, n - 1, 0.0); H.set(n, n, 1.0); for (int i = n - 2; i >= 0; i--) { double ra, sa, vr, vi; ra = 0.0; sa = 0.0; for (int j = l; j <= n; j++) { ra = ra + H.get(i, j) * H.get(j, n - 1); sa = sa + H.get(i, j) * H.get(j, n); } w = H.get(i, i) - p; if (e.get(i) < 0.0) { z = w; r = ra; s = sa; } else { l = i; if (e.get(i) == 0) { double cdiv[] = cdiv(-ra, -sa, w, q); H.set(i, n - 1, cdiv[0]); H.set(i, n, cdiv[1]); } else { // Solve complex equations x = H.get(i, i + 1); y = H.get(i + 1, i); vr = (d.get(i) - p) * (d.get(i) - p) + e.get(i) * e.get(i) - q * q; vi = (d.get(i) - p) * 2.0 * q; if (vr == 0.0 & vi == 0.0) { vr = eps * norm * (Math.abs(w) + Math.abs(q) + Math.abs(x) + Math.abs(y) + Math .abs(z)); } double cdiv[] = cdiv(x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi); H.set(i, n - 1, cdiv[0]); H.set(i, n, cdiv[1]); if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) { H.set(i + 1, n - 1, (-ra - w * H.get(i, n - 1) + q * H.get(i, n)) / x); H.set(i + 1, n, (-sa - w * H.get(i, n) - q * H.get(i, n - 1)) / x); } else { cdiv = cdiv(-r - y * H.get(i, n - 1), -s - y * H.get(i, n), z, q); H.set(i + 1, n - 1, cdiv[0]); H.set(i + 1, n, cdiv[1]); } } // Overflow control t = Math.max(Math.abs(H.get(i, n - 1)), Math.abs(H.get(i, n))); if ((eps * t) * t > 1) { for (int j = i; j <= n; j++) { H.updateAt(j, n - 1, Matrices.asDivFunction(t)); H.updateAt(j, n, Matrices.asDivFunction(t)); } } } } } } // Vectors of isolated roots for (int i = 0; i < nn; i++) { if (i < low | i > high) { for (int j = i; j < nn; j++) { V.set(i, j, H.get(i, j)); } } } // Back transformation to get eigenvectors of original matrix for (int j = nn - 1; j >= low; j--) { for (int i = low; i <= high; i++) { z = 0.0; for (int k = low; k <= Math.min(j, high); k++) { z = z + V.get(i, k) * H.get(k, j); } V.set(i, j, z); } } } private double[] cdiv(double xr, double xi, double yr, double yi) { double cdivr, cdivi; double r, d; if (Math.abs(yr) > Math.abs(yi)) { r = yi / yr; d = yr + r * yi; cdivr = (xr + r * xi) / d; cdivi = (xi - r * xr) / d; } else { r = yr / yi; d = yi + r * yr; cdivr = (r * xr + xi) / d; cdivi = (r * xi - xr) / d; } return new double[] { cdivr, cdivi }; } } la4j-0.6.0/src/main/java/org/la4j/decomposition/LUDecompositor.java000066400000000000000000000041551263320764000250630ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.la4j.Matrix; /** * This class represents LU decomposition of matrices. More details *

* here. *

*/ public class LUDecompositor extends RawLUDecompositor implements MatrixDecompositor { public LUDecompositor(Matrix matrix) { super(matrix); } /** * Returns the result of LU decomposition of given matrix *

* See * http://mathworld.wolfram.com/LUDecomposition.html for more details. *

* * @return { L, U, P } */ @Override public Matrix[] decompose() { Matrix[] lup = super.decompose(); Matrix lu = lup[0]; Matrix p = lup[1]; Matrix l = matrix.blankOfShape(lu.rows(), lu.columns()); for (int i = 0; i < l.rows(); i++) { for (int j = 0; j <= i; j++) { if (i > j) { l.set(i, j, lu.get(i, j)); } else { l.set(i, j, 1.0); } } } Matrix u = matrix.blankOfShape(lu.columns(), lu.columns()); for (int i = 0; i < u.rows(); i++) { for (int j = i; j < u.columns(); j++) { u.set(i, j, lu.get(i, j)); } } return new Matrix[] { l, u, p }; } } la4j-0.6.0/src/main/java/org/la4j/decomposition/MatrixDecompositor.java000066400000000000000000000026361263320764000260110ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.la4j.Matrix; import java.io.Serializable; /** * Interface for implementing various matrix decompositions. More details *

* here. *

*/ public interface MatrixDecompositor extends Serializable { /** * Decomposes the wrapped matrix. * * @return */ Matrix[] decompose(); /** * Returns the self matrix of this decompositor. * * @return */ Matrix self(); /** * Checks whether this decompositor is applicable to given matrix or not. * * @param matrix * @return */ boolean applicableTo(Matrix matrix); } la4j-0.6.0/src/main/java/org/la4j/decomposition/QRDecompositor.java000066400000000000000000000046131263320764000250640ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.la4j.Matrices; import org.la4j.Matrix; /** * This class represents QR decomposition of matrices. More details *

* here. *

*/ public class QRDecompositor extends RawQRDecompositor implements MatrixDecompositor { public QRDecompositor(Matrix matrix) { super(matrix); } /** * Returns the result of QR decomposition of given matrix *

* See * http://mathworld.wolfram.com/QRDecomposition.html for more details. *

* * @return { Q, R } */ @Override public Matrix[] decompose() { Matrix[] qrr = super.decompose(); Matrix qr = qrr[0]; Matrix r = qrr[1]; Matrix q = qr.blank(); for (int k = q.columns() - 1; k >= 0; k--) { q.set(k, k, 1.0); for (int j = k; j < q.columns(); j++) { if (Math.abs(qr.get(k, k)) > Matrices.EPS) { double acc = 0.0; for (int i = k; i < q.rows(); i++) { acc += qr.get(i, k) * q.get(i, j); } acc = -acc / qr.get(k, k); for (int i = k; i < q.rows(); i++) { q.updateAt(i, j, Matrices.asPlusFunction(acc * qr.get(i, k))); } } } } for (int i = 0; i < r.rows(); i++) { for (int j = i + 1; j < r.columns(); j++) { r.set(i, j, qr.get(i, j)); } } return new Matrix[] { q, r }; } } la4j-0.6.0/src/main/java/org/la4j/decomposition/RawLUDecompositor.java000066400000000000000000000043531263320764000255350ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.SparseMatrix; public class RawLUDecompositor extends AbstractDecompositor implements MatrixDecompositor { public RawLUDecompositor(Matrix matrix) { super(matrix); } @Override public Matrix[] decompose() { Matrix lu = matrix.copy(); Matrix p = SparseMatrix.identity(lu.rows()); for (int j = 0; j < lu.columns(); j++) { for (int i = 0; i < lu.rows(); i++) { int kmax = Math.min(i, j); double s = 0.0; for (int k = 0; k < kmax; k++) { s += lu.get(i, k) * lu.get(k, j); } lu.updateAt(i, j, Matrices.asMinusFunction(s)); } int pivot = j; for (int i = j + 1; i < lu.rows(); i++) { if (Math.abs(lu.get(i, j)) > Math.abs(lu.get(pivot, j))) { pivot = i; } } if (pivot != j) { lu.swapRows(pivot, j); p.swapRows(pivot, j); } if (j < lu.rows() && Math.abs(lu.get(j, j)) > Matrices.EPS) { for (int i = j + 1; i < lu.rows(); i++) { lu.updateAt(i, j, Matrices.asDivFunction(lu.get(j, j))); } } } return new Matrix[] { lu, p }; } @Override public boolean applicableTo(Matrix matrix) { return matrix.rows() == matrix.columns(); } } la4j-0.6.0/src/main/java/org/la4j/decomposition/RawQRDecompositor.java000066400000000000000000000045031263320764000255340ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.la4j.Matrices; import org.la4j.Matrix; public class RawQRDecompositor extends AbstractDecompositor implements MatrixDecompositor { public RawQRDecompositor(Matrix matrix) { super(matrix); } @Override public Matrix[] decompose() { Matrix qr = matrix.copy(); Matrix r = matrix.blankOfShape(qr.columns(), qr.columns()); for (int k = 0; k < qr.columns(); k++) { double norm = 0.0; for (int i = k; i < qr.rows(); i++) { norm = Math.hypot(norm, qr.get(i, k)); } if (Math.abs(norm) > Matrices.EPS) { if (qr.get(k, k) < 0.0) { norm = -norm; } for (int i = k; i < qr.rows(); i++) { qr.updateAt(i, k, Matrices.asDivFunction(norm)); } qr.updateAt(k, k, Matrices.INC_FUNCTION); for (int j = k + 1; j < qr.columns(); j++) { double acc = 0.0; for (int i = k; i < qr.rows(); i++) { acc += qr.get(i, k) * qr.get(i, j); } acc = -acc / qr.get(k, k); for (int i = k; i < qr.rows(); i++) { qr.updateAt(i, j, Matrices.asPlusFunction(acc * qr.get(i, k))); } } } r.set(k, k, -norm); } return new Matrix[] { qr, r }; } @Override public boolean applicableTo(Matrix matrix) { return matrix.rows() >= matrix.columns(); } } la4j-0.6.0/src/main/java/org/la4j/decomposition/SingularValueDecompositor.java000066400000000000000000000375741263320764000273370ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Julia Kostyukova * */ package org.la4j.decomposition; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.vector.DenseVector; /** * This class represents singular value decomposition of matrices. More details *

* here.

*/ public class SingularValueDecompositor extends AbstractDecompositor implements MatrixDecompositor { public SingularValueDecompositor(Matrix matrix) { super(matrix); } /** * Returns the result of Singular Value decomposition of given matrix *

* See * http://mathworld.wolfram.com/SingularValueDecomposition.html for more * details. *

* * @return { U, D, V } */ @Override public Matrix[] decompose() { // AHTIUNG: this code derived from Jama Matrix a = matrix.copy(); int n = Math.min(a.rows(), a.columns()); Matrix u = matrix.blankOfShape(a.rows(), n); Matrix s = matrix.blankOfShape(a.columns(), a.columns()); Matrix v = matrix.blankOfShape(a.columns(), a.columns()); Vector e = DenseVector.zero(a.columns()); Vector work = DenseVector.zero(a.rows()); int nct = Math.min(a.rows() - 1, a.columns()); int nrt = Math.max(0, Math.min(a.columns() - 2, a.rows())); for (int k = 0; k < Math.max(nct, nrt); k++) { if (k < nct) { s.set(k, k, 0.0); for (int i = k; i < a.rows(); i++) { s.set(k, k, hypot(s.get(k, k), a.get(i, k))); } if (Math.abs(s.get(k, k)) > Matrices.EPS) { if (a.get(k, k) < 0.0) { s.updateAt(k, k, Matrices.INV_FUNCTION); } double skk = s.get(k, k); for (int i = k; i < a.rows(); i++) { a.updateAt(i, k, Matrices.asDivFunction(skk)); } a.updateAt(k, k, Matrices.INC_FUNCTION); } s.updateAt(k, k, Matrices.INV_FUNCTION); } for (int j = k + 1; j < a.columns(); j++) { if ((k < nct) & (Math.abs(s.get(k, k)) > Matrices.EPS)) { double t = 0; for (int i = k; i < a.rows(); i++) { t += a.get(i, k) * a.get(i, j); } t = -t / a.get(k, k); for (int i = k; i < a.rows(); i++) { a.updateAt(i, j, Matrices.asPlusFunction(t * a.get(i, k))); } } e.set(j, a.get(k, j)); } if (k < nct) { for (int i = k; i < a.rows(); i++) { u.set(i, k, a.get(i, k)); } } if (k < nrt) { e.set(k, 0); for (int i = k + 1; i < a.columns(); i++) { e.set(k, hypot(e.get(k), e.get(i))); } if (Math.abs(e.get(k)) > Matrices.EPS) { if (e.get(k + 1) < 0.0) { e.updateAt(k, Vectors.INV_FUNCTION); } double ek = e.get(k); for (int i = k + 1; i < a.columns(); i++) { e.updateAt(i, Vectors.asDivFunction(ek)); } e.updateAt(k + 1, Vectors.INC_FUNCTION); } e.updateAt(k, Vectors.INV_FUNCTION); if ((k + 1 < a.rows()) && (Math.abs(e.get(k)) > Matrices.EPS)) { for (int i = k + 1; i < a.rows(); i++) { work.set(i, 0.0); } for (int j = k + 1; j < a.columns(); j++) { for (int i = k + 1; i < a.rows(); i++) { work.updateAt(i, Vectors.asPlusFunction(e.get(j) * a.get(i, j))); } } for (int j = k + 1; j < a.columns(); j++) { double t = -e.get(j) / e.get(k + 1); for (int i = k + 1; i < a.rows(); i++) { a.updateAt(i, j, Matrices.asPlusFunction(t * work.get(i))); } } } for (int i = k + 1; i < a.columns(); i++) { v.set(i, k, e.get(i)); } } } int p = Math.min(a.columns(), a.rows() + 1); if (nct < a.columns()) { s.set(nct, nct, a.get(nct, nct)); } if (a.rows() < p) { s.set(p - 1, p - 1, 0.0); } if (nrt + 1 < p) { e.set(nrt, a.get(nrt, p - 1)); } e.set(p - 1, 0.0); for (int j = nct; j < n; j++) { for (int i = 0; i < a.rows(); i++) { u.set(i, j, 0.0); } u.set(j, j, 1.0); } for (int k = nct - 1; k >= 0; k--) { if (Math.abs(s.get(k, k)) > Matrices.EPS) { for (int j = k + 1; j < n; j++) { double t = 0; for (int i = k; i < a.rows(); i++) { t += u.get(i, k) * u.get(i, j); } t = -t / u.get(k, k); for (int i = k; i < a.rows(); i++) { u.updateAt(i, j, Matrices.asPlusFunction(t * u.get(i, k))); } } for (int i = k; i < a.rows(); i++) { u.updateAt(i, k, Matrices.INV_FUNCTION); } u.updateAt(k, k, Matrices.INC_FUNCTION); for (int i = 0; i < k - 1; i++) { u.set(i, k, 0.0); } } else { for (int i = 0; i < a.rows(); i++) { u.set(i, k, 0.0); } u.set(k, k, 1.0); } } for (int k = n - 1; k >= 0; k--) { if ((k < nrt) & (Math.abs(e.get(k)) > Matrices.EPS)) { for (int j = k + 1; j < n; j++) { double t = 0; for (int i = k + 1; i < a.columns(); i++) { t += v.get(i, k) * v.get(i, j); } t = -t / v.get(k + 1, k); for (int i = k + 1; i < a.columns(); i++) { v.updateAt(i, j, Matrices.asPlusFunction(t * v.get(i, k))); } } } for (int i = 0; i < a.columns(); i++) { v.set(i, k, 0.0); } v.set(k, k, 1.0); } int pp = p - 1; int iter = 0; double eps = Math.pow(2.0, -52.0); double tiny = Math.pow(2.0, -966.0); while (p > 0) { int k, kase; for (k = p - 2; k >= -1; k--) { if (k == -1) break; if (Math.abs(e.get(k)) <= tiny + eps * (Math.abs(s.get(k, k)) + Math.abs(s.get(k + 1, k + 1)))) { e.set(k, 0.0); break; } } if (k == p - 2) { kase = 4; } else { int ks; for (ks = p - 1; ks >= k; ks--) { if (ks == k) break; double t = (ks != p ? Math.abs(e.get(ks)) : 0.) + (ks != k + 1 ? Math.abs(e.get(ks - 1)) : 0.); if (Math.abs(s.get(ks, ks)) <= tiny + eps * t) { s.set(ks, ks, 0.0); break; } } if (ks == k) { kase = 3; } else if (ks == p - 1) { kase = 1; } else { kase = 2; k = ks; } } k++; switch (kase) { case 1: { double f = e.get(p - 2); e.set(p - 2, 0.0); for (int j = p - 2; j >= k; j--) { double t = hypot(s.get(j, j), f); double cs = s.get(j, j) / t; double sn = f / t; s.set(j, j, t); if (j != k) { f = -sn * e.get(j - 1); e.set(j - 1, cs * e.get(j - 1)); } for (int i = 0; i < a.columns(); i++) { t = cs * v.get(i, j) + sn * v.get(i, p - 1); v.set(i, p - 1, -sn * v.get(i, j) + cs * v.get(i, p - 1)); v.set(i, j, t); } } } break; case 2: { double f = e.get(k - 1); e.set(k - 1, 0.0); for (int j = k; j < p; j++) { double t = hypot(s.get(j, j), f); double cs = s.get(j, j) / t; double sn = f / t; s.set(j, j, t); f = -sn * e.get(j); e.set(j, cs * e.get(j)); for (int i = 0; i < a.rows(); i++) { t = cs * u.get(i, j) + sn * u.get(i, k - 1); u.set(i, k - 1, -sn * u.get(i, j) + cs * u.get(i, k - 1)); u.set(i, j, t); } } } break; case 3: { double scale = Math.max( Math.max(Math.max( Math.max(Math.abs(s.get(p - 1, p - 1)), Math.abs(s.get(p - 2, p - 2))), Math.abs(e.get(p - 2))), Math.abs(s.get(k, k))), Math.abs(e.get(k))); double sp = s.get(p - 1, p - 1) / scale; double spm1 = s.get(p - 2, p - 2) / scale; double epm1 = e.get(p - 2) / scale; double sk = s.get(k, k) / scale; double ek = e.get(k) / scale; double b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2.0; double c = (sp * epm1) * (sp * epm1); double shift = 0.0; if ((b != 0.0) | (c != 0.0)) { shift = Math.sqrt(b * b + c); if (b < 0.0) { shift = -shift; } shift = c / (b + shift); } double f = (sk + sp) * (sk - sp) + shift; double g = sk * ek; for (int j = k; j < p - 1; j++) { double t = hypot(f, g); double cs = f / t; double sn = g / t; if (j != k) { e.set(j - 1, t); } f = cs * s.get(j, j) + sn * e.get(j); e.set(j, cs * e.get(j) - sn * s.get(j, j)); g = sn * s.get(j + 1, j + 1); s.set(j + 1, j + 1, cs * s.get(j + 1, j + 1)); for (int i = 0; i < a.columns(); i++) { t = cs * v.get(i, j) + sn * v.get(i, j + 1); v.set(i, j + 1, -sn * v.get(i, j) + cs * v.get(i, j + 1)); v.set(i, j, t); } t = hypot(f, g); cs = f / t; sn = g / t; s.set(j, j, t); f = cs * e.get(j) + sn * s.get(j + 1, j + 1); s.set(j + 1, j + 1, -sn * e.get(j) + cs * s.get(j + 1, j + 1)); g = sn * e.get(j + 1); e.updateAt(j + 1, Vectors.asMulFunction(cs)); if (j < a.rows() - 1) { for (int i = 0; i < a.rows(); i++) { t = cs * u.get(i, j) + sn * u.get(i, j + 1); u.set(i, j + 1, -sn * u.get(i, j) + cs * u.get(i, j + 1)); u.set(i, j, t); } } } e.set(p - 2, f); iter = iter + 1; } break; case 4: { if (s.get(k, k) <= 0.0) { s.set(k, k, s.get(k, k) < 0.0 ? -s.get(k, k) : 0.0); for (int i = 0; i <= pp; i++) { v.updateAt(i, k, Matrices.INV_FUNCTION); } } while (k < pp) { if (s.get(k, k) >= s.get(k + 1, k + 1)) { break; } double t = s.get(k, k); s.set(k, k, s.get(k + 1, k + 1)); s.set(k + 1, k + 1, t); if (k < a.columns() - 1) { for (int i = 0; i < a.columns(); i++) { t = v.get(i, k + 1); v.set(i, k + 1, v.get(i, k)); v.set(i, k, t); } } if (k < a.rows() - 1) { for (int i = 0; i < a.rows(); i++) { t = u.get(i, k + 1); u.set(i, k + 1, u.get(i, k)); u.set(i, k, t); } } k++; } iter = 0; p--; } break; } } // TODO: // We need to change the logic of this code in order do not use resize // It is also not a good idea to use SVN for [m < n] matrices // We need to change it in further releases return new Matrix[] { u, s.copyOfShape(n, a.columns()), v }; } private double hypot(double a, double b) { double result; if (Math.abs(a) > Math.abs(b)) { result = b / a; result = Math.abs(a) * Math.sqrt(1 + result * result); } else if (b != 0) { result = a / b; result = Math.abs(b) * Math.sqrt(1 + result * result); } else { result = 0.0; } return result; } @Override public boolean applicableTo(Matrix matrix) { return true; } } la4j-0.6.0/src/main/java/org/la4j/inversion/000077500000000000000000000000001263320764000204435ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/inversion/GaussJordanInverter.java000066400000000000000000000036671263320764000252610ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.inversion; import org.la4j.LinearAlgebra; import org.la4j.linear.LinearSystemSolver; import org.la4j.Matrix; import org.la4j.Vector; import org.la4j.vector.DenseVector; public class GaussJordanInverter implements MatrixInverter { private final Matrix matrix; public GaussJordanInverter(Matrix matrix) { this.matrix = matrix; } @Override public Matrix inverse() { if (matrix.rows() != matrix.columns()) { throw new IllegalArgumentException("Wrong matrix size: " + "rows != columns"); } Matrix result = matrix.blankOfShape(matrix.rows(), matrix.columns()); for (int i = 0; i < matrix.rows(); i++) { Vector b = DenseVector.zero(matrix.rows()); b.set(i, 1.0); try { LinearSystemSolver solver = matrix.withSolver(LinearAlgebra.GAUSSIAN); Vector x = solver.solve(b); result.setColumn(i, x); } catch (IllegalArgumentException ex) { throw new IllegalArgumentException("This matrix is not invertible."); } } return result; } @Override public Matrix self() { return matrix; } } la4j-0.6.0/src/main/java/org/la4j/inversion/MatrixInverter.java000066400000000000000000000020361263320764000242720ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.inversion; import org.la4j.Matrix; import java.io.Serializable; public interface MatrixInverter extends Serializable { /** * Inverse matrix. * * @return */ Matrix inverse(); /** * Returns the self matrix of this inverter. * * @return */ Matrix self(); } la4j-0.6.0/src/main/java/org/la4j/inversion/NoPivotGaussInverter.java000066400000000000000000000043311263320764000254270ustar00rootroot00000000000000/* * Copyright 2011-2015, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.inversion; import org.la4j.Matrix; public class NoPivotGaussInverter implements MatrixInverter { private final Matrix matrix; public NoPivotGaussInverter(final Matrix matrix) { this.matrix = matrix; } @Override public Matrix inverse() { if (matrix.rows() != matrix.columns()) { throw new IllegalArgumentException("Wrong matrix size: " + "rows != columns"); } double var; final Matrix result = matrix.copy(); for (int k = 0; k < matrix.rows(); k++) { final double diagonalTerm = result.get(k, k); if (Math.abs(diagonalTerm) <= Double.MIN_VALUE) { throw new IllegalArgumentException( "This matrix cannot be inverted with a non-pivoting Gauss elimination method."); } var = 1.0 / result.get(k, k); result.set(k, k, 1.0); for (int j = 0; j < matrix.rows(); j++) { result.set(k, j, result.get(k, j) * var); } for (int i = 0; i < matrix.rows(); i++) { if (i == k) { continue; } var = result.get(i, k); result.set(i, k, 0.0); for (int j = 0; j < matrix.rows(); j++) { result.set(i, j, result.get(i, j) - var * result.get(k, j)); } } } return result; } @Override public Matrix self() { return matrix; } } la4j-0.6.0/src/main/java/org/la4j/iterator/000077500000000000000000000000001263320764000202605ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/iterator/ColumnMajorMatrixIterator.java000066400000000000000000000033771263320764000262620ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; public abstract class ColumnMajorMatrixIterator extends MatrixIterator { public ColumnMajorMatrixIterator(int rows, int columns) { super(rows, columns); } @Override protected int cursor() { return columnIndex() * rows + rowIndex(); } @Override public MatrixIterator orElseAdd(final MatrixIterator those) { return new CursorToColumnMajorMatrixIterator(super.orElse(those, JoinFunction.ADD), rows, columns); } @Override public MatrixIterator orElseSubtract(final MatrixIterator those) { return new CursorToColumnMajorMatrixIterator(super.orElse(those, JoinFunction.SUB), rows, columns); } @Override public MatrixIterator andAlsoMultiply(MatrixIterator those) { return new CursorToColumnMajorMatrixIterator(super.andAlso(those, JoinFunction.MUL), rows, columns); } @Override public MatrixIterator andAlsoDivide(MatrixIterator those) { return new CursorToColumnMajorMatrixIterator(super.andAlso(those, JoinFunction.DIV), rows, columns); } } la4j-0.6.0/src/main/java/org/la4j/iterator/CursorIterator.java000066400000000000000000000154441263320764000241220ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; import java.util.Arrays; import java.util.Collection; import java.util.EnumSet; import java.util.Iterator; abstract class CursorIterator implements Iterator { private enum IteratorState { TAKEN_FROM_THESE, TAKEN_FROM_THOSE, THESE_ARE_EMPTY, THOSE_ARE_EMPTY, } private static final Collection TAKEN_FROM_BOTH = Arrays.asList( IteratorState.TAKEN_FROM_THESE, IteratorState.TAKEN_FROM_THOSE ); public abstract double get(); public abstract void set(double value); protected abstract int cursor(); protected CursorIterator orElse(final CursorIterator those, final JoinFunction function) { final CursorIterator these = this; return new CursorIterator() { private final EnumSet state = EnumSet.copyOf(TAKEN_FROM_BOTH); @Override public int cursor() { if (state.contains(IteratorState.TAKEN_FROM_THESE)) { return these.cursor(); } else { return those.cursor(); } } @Override public double get() { if (state.contains(IteratorState.TAKEN_FROM_THESE) && state.contains(IteratorState.TAKEN_FROM_THOSE)) { return function.apply(these.get(), those.get()); } else if (state.contains(IteratorState.TAKEN_FROM_THESE)) { return function.apply(these.get(), 0.0); } else { return function.apply(0.0, those.get()); } } @Override public void set(double value) { throw new UnsupportedOperationException("Composed iterators are read-only for now."); } @Override public boolean hasNext() { if (these.hasNext() || those.hasNext()) { return true; } if (state.contains(IteratorState.TAKEN_FROM_THESE) && state.contains(IteratorState.THOSE_ARE_EMPTY)) { return false; } if (state.contains(IteratorState.TAKEN_FROM_THOSE) && state.contains(IteratorState.THESE_ARE_EMPTY)) { return false; } return !state.containsAll(TAKEN_FROM_BOTH); } @Override public Double next() { if (state.contains(IteratorState.TAKEN_FROM_THESE)) { if (these.hasNext()) { these.next(); } else { state.add(IteratorState.THESE_ARE_EMPTY); } } if (state.contains(IteratorState.TAKEN_FROM_THOSE)) { if (those.hasNext()) { those.next(); } else { state.add(IteratorState.THOSE_ARE_EMPTY); } } state.remove(IteratorState.TAKEN_FROM_THESE); state.remove(IteratorState.TAKEN_FROM_THOSE); if (!state.contains(IteratorState.THESE_ARE_EMPTY) && !state.contains(IteratorState.THOSE_ARE_EMPTY)) { if (these.cursor() < those.cursor()) { state.add(IteratorState.TAKEN_FROM_THESE); } else if (these.cursor() > those.cursor()) { state.add(IteratorState.TAKEN_FROM_THOSE); } else { state.add(IteratorState.TAKEN_FROM_THESE); state.add(IteratorState.TAKEN_FROM_THOSE); } } else if (state.contains(IteratorState.THESE_ARE_EMPTY)) { state.add(IteratorState.TAKEN_FROM_THOSE); } else if (state.contains(IteratorState.THOSE_ARE_EMPTY)) { state.add(IteratorState.TAKEN_FROM_THESE); } return get(); } }; } protected CursorIterator andAlso(final CursorIterator those, final JoinFunction function) { final CursorIterator these = this; return new CursorIterator() { private boolean hasNext; private double prevValue, currValue; private int prevCursor, currCursor; { doNext(); } @Override public int cursor() { return prevCursor; } private void doNext() { hasNext = false; prevValue = currValue; prevCursor = currCursor; if (these.hasNext() && those.hasNext()) { these.next(); those.next(); while (these.cursor() != those.cursor()) { if (these.cursor() < those.cursor() && these.hasNext()) { these.next(); } else if (these.cursor() > those.cursor() && those.hasNext()) { those.next(); } else { return; } } hasNext = true; currValue = function.apply(these.get(), those.get()); currCursor = these.cursor(); } } @Override public double get() { return prevValue; } @Override public void set(double value) { throw new UnsupportedOperationException("Composed iterators are read-only for now."); } @Override public boolean hasNext() { return hasNext; } @Override public Double next() { doNext(); return get(); } }; } @Override public void remove() { throw new UnsupportedOperationException("This will be supported in 0.6.0."); } } la4j-0.6.0/src/main/java/org/la4j/iterator/CursorToColumnMajorMatrixIterator.java000066400000000000000000000030651263320764000277550ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; public class CursorToColumnMajorMatrixIterator extends ColumnMajorMatrixIterator { private final CursorIterator underlying; public CursorToColumnMajorMatrixIterator(CursorIterator underlying, int rows, int columns) { super(rows, columns); this.underlying = underlying; } @Override public int rowIndex() { return underlying.cursor() - columnIndex() * rows; } @Override public int columnIndex() { return underlying.cursor() / rows; } @Override public double get() { return underlying.get(); } @Override public void set(double value) { underlying.set(value); } @Override public boolean hasNext() { return underlying.hasNext(); } @Override public Double next() { return underlying.next(); } } la4j-0.6.0/src/main/java/org/la4j/iterator/CursorToRowMajorMatrixIterator.java000066400000000000000000000030501263320764000272610ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; class CursorToRowMajorMatrixIterator extends RowMajorMatrixIterator { private final CursorIterator underlying; public CursorToRowMajorMatrixIterator(CursorIterator underlying, int rows, int columns) { super(rows, columns); this.underlying = underlying; } @Override public int rowIndex() { return underlying.cursor() / columns; } @Override public int columnIndex() { return underlying.cursor() - rowIndex() * columns; } @Override public double get() { return underlying.get(); } @Override public void set(double value) { underlying.set(value); } @Override public boolean hasNext() { return underlying.hasNext(); } @Override public Double next() { return underlying.next(); } } la4j-0.6.0/src/main/java/org/la4j/iterator/CursorToVectorIterator.java000066400000000000000000000026021263320764000256000ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; class CursorToVectorIterator extends VectorIterator { private final CursorIterator underlying; public CursorToVectorIterator(CursorIterator underlying, int length) { super(length); this.underlying = underlying; } @Override public int index() { return underlying.cursor(); } @Override public double get() { return underlying.get(); } @Override public void set(double value) { underlying.set(value); } @Override public boolean hasNext() { return underlying.hasNext(); } @Override public Double next() { return underlying.next(); } } la4j-0.6.0/src/main/java/org/la4j/iterator/JoinFunction.java000066400000000000000000000033131263320764000235300ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; // TODO: need a better name abstract class JoinFunction { public abstract double apply(double a, double b); public static final JoinFunction ADD = new JoinFunction() { @Override public double apply(double a, double b) { return a + b; } }; public static final JoinFunction SUB = new JoinFunction() { @Override public double apply(double a, double b) { return a - b; } }; public static final JoinFunction MUL = new JoinFunction() { @Override public double apply(double a, double b) { return a * b; } }; public static final JoinFunction DIV = new JoinFunction() { @Override public double apply(double a, double b) { return a / b; } }; public static final JoinFunction MOD = new JoinFunction() { @Override public double apply(double a, double b) { return a % b; } }; } la4j-0.6.0/src/main/java/org/la4j/iterator/MatrixIterator.java000066400000000000000000000025401263320764000241020ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; public abstract class MatrixIterator extends CursorIterator { protected final int rows; protected final int columns; public MatrixIterator(int rows, int columns) { this.rows = rows; this.columns = columns; } public abstract int rowIndex(); public abstract int columnIndex(); public abstract MatrixIterator orElseAdd(final MatrixIterator those); public abstract MatrixIterator orElseSubtract(final MatrixIterator those); public abstract MatrixIterator andAlsoMultiply(final MatrixIterator those); public abstract MatrixIterator andAlsoDivide(final MatrixIterator those); } la4j-0.6.0/src/main/java/org/la4j/iterator/RowMajorMatrixIterator.java000066400000000000000000000033601263320764000255640ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; public abstract class RowMajorMatrixIterator extends MatrixIterator { public RowMajorMatrixIterator(int rows, int columns) { super(rows, columns); } @Override protected int cursor() { return rowIndex() * columns + columnIndex(); } @Override public MatrixIterator orElseAdd(final MatrixIterator those) { return new CursorToRowMajorMatrixIterator(super.orElse(those, JoinFunction.ADD), rows, columns); } @Override public MatrixIterator orElseSubtract(final MatrixIterator those) { return new CursorToRowMajorMatrixIterator(super.orElse(those, JoinFunction.SUB), rows, columns); } @Override public MatrixIterator andAlsoMultiply(MatrixIterator those) { return new CursorToRowMajorMatrixIterator(super.andAlso(those, JoinFunction.MUL), rows, columns); } @Override public MatrixIterator andAlsoDivide(MatrixIterator those) { return new CursorToRowMajorMatrixIterator(super.andAlso(those, JoinFunction.DIV), rows, columns); } } la4j-0.6.0/src/main/java/org/la4j/iterator/VectorIterator.java000066400000000000000000000040101263320764000240720ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.iterator; public abstract class VectorIterator extends CursorIterator { protected final int length; public VectorIterator(int length) { this.length = length; } /** * Returns an index of the current cell. * * @return an index of the current cell */ public abstract int index(); public VectorIterator orElseAdd(final VectorIterator those) { return new CursorToVectorIterator(super.orElse(those, JoinFunction.ADD), length); } public VectorIterator orElseSubtract(final VectorIterator those) { return new CursorToVectorIterator(super.orElse(those, JoinFunction.SUB), length); } public VectorIterator andAlsoMultiply(final VectorIterator those) { return new CursorToVectorIterator(super.andAlso(those, JoinFunction.MUL), length); } public VectorIterator andAlsoDivide(final VectorIterator those) { return new CursorToVectorIterator(super.andAlso(those, JoinFunction.DIV), length); } public double innerProduct(final VectorIterator those) { VectorIterator both = this.andAlsoMultiply(those); double acc = 0.0; while (both.hasNext()) { acc += both.next(); } return acc; } @Override protected int cursor() { return index(); } } la4j-0.6.0/src/main/java/org/la4j/linear/000077500000000000000000000000001263320764000177015ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/linear/AbstractSolver.java000066400000000000000000000033231263320764000235030ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.Matrix; import org.la4j.Vector; public abstract class AbstractSolver implements LinearSystemSolver { // TODO: rename a to matrix protected Matrix a; protected int unknowns; protected int equations; protected AbstractSolver(Matrix a) { if (!applicableTo(a)) { fail("Given coefficient matrix can not be used with this solver."); } this.a = a; this.unknowns = a.columns(); this.equations = a.rows(); } @Override public Matrix self() { return a; } @Override public int unknowns() { return unknowns; } @Override public int equations() { return equations; } protected void ensureRHSIsCorrect(Vector vector) { if (vector.length() != equations) { fail("Wrong length of RHS vector: " + vector.length() + "."); } } protected void fail(String message) { throw new IllegalArgumentException(message); } } la4j-0.6.0/src/main/java/org/la4j/linear/ForwardBackSubstitutionSolver.java000066400000000000000000000052351263320764000265660ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.LinearAlgebra; import org.la4j.decomposition.MatrixDecompositor; import org.la4j.Matrix; import org.la4j.Vector; import org.la4j.Vectors; public class ForwardBackSubstitutionSolver extends AbstractSolver implements LinearSystemSolver { private static final long serialVersionUID = 4071505L; // Matrices from RAW_LU decomposition private final Matrix lu; private final Matrix p; public ForwardBackSubstitutionSolver(Matrix a) { super(a); // we use Raw LU for this MatrixDecompositor decompositor = a.withDecompositor(LinearAlgebra.RAW_LU); Matrix[] lup = decompositor.decompose(); // TODO: it doesn't look safe. this.lu = lup[0]; this.p = lup[1]; } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); int n = unknowns(); // checks whether the lu matrix is singular or not for (int i = 0; i < n; i++) { if (lu.get(i, i) == 0.0) { fail("This system can not be solved: coefficient matrix is singular."); } } Vector x = b.blankOfLength(n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (p.get(i, j) != 0.0) { x.set(i, b.get(j)); break; } } } for (int j = 0; j < n; j++) { for (int i = j + 1; i < n; i++) { x.updateAt(i, Vectors.asMinusFunction(x.get(j) * lu.get(i, j))); } } for (int j = n - 1; j >= 0; j--) { x.updateAt(j, Vectors.asDivFunction(lu.get(j, j))); for (int i = 0; i < j; i++) { x.updateAt(i, Vectors.asMinusFunction(x.get(j) * lu.get(i, j))); } } return x; } @Override public boolean applicableTo(Matrix matrix) { return matrix.rows() == matrix.columns(); } } la4j-0.6.0/src/main/java/org/la4j/linear/GaussianSolver.java000066400000000000000000000065031263320764000235150ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.Vector; /** * This class represents Gaussian method for solving linear systems. More details *

* here. *

*/ public class GaussianSolver extends AbstractSolver implements LinearSystemSolver { private static final long serialVersionUID = 4071505L; // augmented matrix private final Matrix aa; public GaussianSolver(Matrix a) { super(a); this.aa = a.copyOfColumns(unknowns() + 1); } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); // extend augmented matrix aa.setColumn(unknowns(), b); // the 1st phase triangularizeWithPivoting(aa); if (Math.abs(aa.diagonalProduct()) < Matrices.EPS) { fail("This system is singular."); } // the 2nd phase Vector x = b.blankOfLength(aa.columns() - 1); backSubstitution(aa, x); return x; } private void triangularizeWithPivoting(Matrix matrix) { for (int i = 0; i + 1 < matrix.rows(); i++) { int maxIndex = i; double maxItem = Math.abs(matrix.get(i, i)); for (int k = i + 1; k < matrix.rows(); k++) { double value = Math.abs(matrix.get(k, i)); if (value > maxItem) { maxItem = value; maxIndex = k; } } if (maxItem == 0.0) { throw new IllegalArgumentException("This system can't be solved."); } if (maxIndex > i) { matrix.swapRows(maxIndex, i); } for (int j = i + 1; j < matrix.rows(); j++) { double c = matrix.get(j, i) / matrix.get(i, i); matrix.set(j, i, 0.0); for (int k = i + 1; k < matrix.columns(); k++) { matrix.updateAt(j, k, Matrices.asMinusFunction(matrix.get(i, k) * c)); } } } } private void backSubstitution(Matrix matrix, Vector result) { for (int i = matrix.rows() - 1; i >= 0; i--) { double acc = 0.0; for (int j = i + 1; j < matrix.columns() - 1; j++) { acc += result.get(j) * matrix.get(i, j); } result.set(i, (matrix.get(i, matrix.columns() - 1) - acc) / matrix.get(i, i)); } } @Override public boolean applicableTo(Matrix matrix) { return matrix.rows() == matrix.columns(); } } la4j-0.6.0/src/main/java/org/la4j/linear/JacobiSolver.java000066400000000000000000000047011263320764000231300ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.functor.MatrixFunction; import org.la4j.Vector; /** * This class represents Jacobi method for solving linear systems. More details *

* here. *

*/ public class JacobiSolver extends AbstractSolver implements LinearSystemSolver { private static final long serialVersionUID = 4071505L; private final Matrix aa; public JacobiSolver(Matrix a) { super(a); // We need a copy here, since we don't want to change source matrix this.aa = a.copy(); for (int i = 0; i < aa.rows(); i++) { MatrixFunction divider = Matrices.asDivFunction(aa.get(i, i)); for (int j = 0; j < aa.columns(); j++) { if (i != j) { aa.updateAt(i, j, divider); } } } } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); Vector current =b.blankOfLength(unknowns()); // while it is not a solution while (!a.multiply(current).equals(b)) { Vector next = current.blank(); for (int i = 0; i < aa.rows(); i++) { double acc = b.get(i) / aa.get(i, i); for (int j = 0; j < aa.columns(); j++) { if (i != j) { acc -= aa.get(i, j) * current.get(j); } } next.set(i, acc); } current = next; } return current; } @Override public boolean applicableTo(Matrix matrix) { return matrix.is(Matrices.DIAGONALLY_DOMINANT_MATRIX); } } la4j-0.6.0/src/main/java/org/la4j/linear/LeastNormSolver.java000066400000000000000000000034271263320764000236510ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Maxim Samoylov * */ package org.la4j.linear; import org.la4j.LinearAlgebra; import org.la4j.Matrix; import org.la4j.Vector; /** * This class provides solution of "fat" linear system with least euclidean norm. * See details *

* here. *

*/ public class LeastNormSolver extends AbstractSolver implements LinearSystemSolver { protected LeastNormSolver(Matrix a) { super(a); } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); Matrix temp = self().multiply(self().rotate()); Matrix pseudoInverse = self().rotate().multiply(temp.withInverter(LinearAlgebra.InverterFactory.GAUSS_JORDAN).inverse()); return pseudoInverse.multiply(b); } @Override public boolean applicableTo(Matrix matrix) { //TODO: we need to think about how to improve the speed here. //Note: Matrix.rank() works for O(N^3) which is quite slow. int r = matrix.rank(); return (r == matrix.rows() || r == matrix.columns()); } } la4j-0.6.0/src/main/java/org/la4j/linear/LeastSquaresSolver.java000066400000000000000000000051511263320764000243550ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.LinearAlgebra; import org.la4j.decomposition.MatrixDecompositor; import org.la4j.Matrix; import org.la4j.Vector; import org.la4j.Vectors; public class LeastSquaresSolver extends AbstractSolver implements LinearSystemSolver { private static final long serialVersionUID = 4071505L; // Matrices from RAW_QR decomposition private final Matrix qr; private final Matrix r; public LeastSquaresSolver(Matrix a) { super(a); // we use QR for this MatrixDecompositor decompositor = a.withDecompositor(LinearAlgebra.RAW_QR); Matrix[] qrr = decompositor.decompose(); // TODO: Do something with it. this.qr = qrr[0]; this.r = qrr[1]; } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); int n = unknowns(); int m = equations(); // check whether the matrix is full-rank or not for (int i = 0; i < r.rows(); i++) { if (r.get(i, i) == 0.0) { fail("This system can not be solved: coefficient matrix is rank deficient."); } } Vector x = b.copy(); for (int j = 0; j < n; j++) { double acc = 0.0; for (int i = j; i < m; i++) { acc += qr.get(i, j) * x.get(i); } acc = -acc / qr.get(j, j); for (int i = j; i < m; i++) { x.updateAt(i, Vectors.asPlusFunction(acc * qr.get(i, j))); } } for (int j = n - 1; j >= 0; j--) { x.updateAt(j, Vectors.asDivFunction(r.get(j, j))); for (int i = 0; i < j; i++) { x.updateAt(i, Vectors.asMinusFunction(x.get(j) * qr.get(i, j))); } } return x.slice(0, n); } @Override public boolean applicableTo(Matrix matrix) { return matrix.rows() >= matrix.columns(); } } la4j-0.6.0/src/main/java/org/la4j/linear/LinearSystemSolver.java000066400000000000000000000030711263320764000243570ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import java.io.Serializable; import org.la4j.Matrix; import org.la4j.Vector; /** * Linear System Solver interface; * This class implements Strategy design pattern; */ public interface LinearSystemSolver extends Serializable { /** * Solves the system A*x = b. * * @param b * @return */ Vector solve(Vector b); /** * Returns the self matrix of the solver. * * @return */ Matrix self(); /** * Returns the number os unknowns in this solver. * * @return */ int unknowns(); /** * Returns the number of equations in this solver. * * @return */ int equations(); /** * Checks whether this solver applicable to given {@code matrix} or not. * * @param matrix */ boolean applicableTo(Matrix matrix); } la4j-0.6.0/src/main/java/org/la4j/linear/SeidelSolver.java000066400000000000000000000045001263320764000231430ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.functor.MatrixFunction; import org.la4j.Vector; /** * This class represents * Seidel method * for solving linear systems. */ public class SeidelSolver extends AbstractSolver implements LinearSystemSolver { private static final long serialVersionUID = 4071505L; private final Matrix aa; public SeidelSolver(Matrix a) { super(a); // We need a copy here, since we don't want to change source matrix this.aa = a.copy(); for (int i = 0; i < aa.rows(); i++) { MatrixFunction divider = Matrices.asDivFunction(aa.get(i, i)); for (int j = 0; j < aa.columns(); j++) { if (i != j) { aa.updateAt(i, j, divider); } } } } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); Vector current = b.blankOfLength(unknowns()); while (!a.multiply(current).equals(b)) { for (int i = 0; i < aa.rows(); i++) { double acc = b.get(i) / aa.get(i, i); for (int j = 0; j < aa.columns(); j++) { if (i != j) { acc -= aa.get(i, j) * current.get(j); } } current.set(i, acc); } } return current; } @Override public boolean applicableTo(Matrix matrix) { return matrix.is(Matrices.DIAGONALLY_DOMINANT_MATRIX); } } la4j-0.6.0/src/main/java/org/la4j/linear/SquareRootSolver.java000066400000000000000000000057541263320764000240560ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.Vector; /** * This class represents Square Root method * for solving linear systems. */ public class SquareRootSolver extends AbstractSolver implements LinearSystemSolver { private static final long serialVersionUID = 4071505L; public SquareRootSolver(Matrix a) { super(a); } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); Matrix s = a.blank(); Matrix d = a.blank(); Vector x = b.blankOfLength(unknowns()); Vector y = b.blankOfLength(unknowns()); Vector z = b.blankOfLength(unknowns()); for (int i = 0; i < a.rows(); i++) { double dd = 0.0; for (int l = 0; l < i; l++) { double sli = s.get(l, i); dd += sli * sli * d.get(l, l); } d.set(i, i, Math.signum(a.get(i, i) - dd)); s.set(i, i, Math.sqrt(Math.abs(a.get(i, i) - dd))); if (s.get(i, i) == 0.0) { // TODO: we can try to rearrange the diagonal elements fail("This matrix is singular. We can't solve it."); } for (int j = i + 1; j < a.columns(); j++) { double acc = 0; for (int l = 0; l < i; l++) { double sli = s.get(l, i); double slj = s.get(l, j); acc += sli * slj * d.get(l, l); } s.set(i, j, (a.get(i, j) - acc) / (s.get(i, i) * d.get(i, i))); } double zz = 0.0; for (int l = 0; l < i; l++) { zz += z.get(l) * s.get(l, i); } z.set(i, (b.get(i) - zz) / s.get(i, i)); y.set(i, z.get(i) / d.get(i, i)); } for (int i = a.rows() - 1; i >= 0; i--) { double acc = 0.0; for (int l = i + 1; l < a.columns(); l++) { acc += x.get(l) * s.get(i, l); } x.set(i, (y.get(i) - acc) / s.get(i, i)); } return x; } @Override public boolean applicableTo(Matrix matrix) { return matrix.is(Matrices.SYMMETRIC_MATRIX); } } la4j-0.6.0/src/main/java/org/la4j/linear/SweepSolver.java000066400000000000000000000053711263320764000230300ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.Vector; import org.la4j.Vectors; /** * This class represents Sweep (or * Tridiagonal matrix, or Thomas) method for solving linear systems. */ public class SweepSolver extends AbstractSolver implements LinearSystemSolver { private static final long serialVersionUID = 4071505L; public SweepSolver(Matrix a) { super(a); } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); // We need a copy, since the algorithm changes data Matrix aa = a.copy(); Vector bb = b.copy(); Vector x = b.blankOfLength(aa.columns()); for (int i = 0; i < aa.rows() - 1; i++) { double maxItem = Math.abs(aa.get(i, i)); int maxIndex = i; for (int j = i + 1; j < aa.columns(); j++) { double value = Math.abs(aa.get(j, i)); if (value > maxItem) { maxItem = value; maxIndex = j; } } if (maxIndex != i) { aa.swapRows(maxIndex, i); bb.swapElements(i, maxIndex); } for (int j = i + 1; j < aa.columns(); j++) { double c = aa.get(j, i) / aa.get(i, i); for (int k = i; k < aa.columns(); k++) { aa.updateAt(j, k, Matrices.asMinusFunction(aa.get(i, k) * c)); } bb.updateAt(j, Vectors.asMinusFunction(bb.get(i) * c)); } } for (int i = aa.rows() - 1; i >= 0; i--) { double acc = 0.0; for (int j = i + 1; j < aa.columns(); j++) { acc += aa.get(i, j) * x.get(j); } x.set(i, (bb.get(i) - acc) / aa.get(i, i)); } return x; } @Override public boolean applicableTo(Matrix matrix) { return matrix.is(Matrices.TRIDIAGONAL_MATRIX); } } la4j-0.6.0/src/main/java/org/la4j/matrix/000077500000000000000000000000001263320764000177335ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/matrix/ColumnMajorSparseMatrix.java000066400000000000000000000142611263320764000253730ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix; import org.la4j.Matrices; import org.la4j.iterator.ColumnMajorMatrixIterator; import org.la4j.iterator.MatrixIterator; import org.la4j.Matrix; import org.la4j.matrix.sparse.CCSMatrix; import org.la4j.operation.MatrixMatrixOperation; import org.la4j.operation.MatrixOperation; import org.la4j.operation.MatrixVectorOperation; import org.la4j.Vector; import java.util.Iterator; import java.util.Random; public abstract class ColumnMajorSparseMatrix extends SparseMatrix { /** * Creates a zero {@link ColumnMajorSparseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static ColumnMajorSparseMatrix zero(int rows, int columns) { return CCSMatrix.zero(rows, columns); } /** * Creates a zero {@link ColumnMajorSparseMatrix} of the given shape: * {@code rows} x {@code columns} with the given {@code capacity}. */ public static ColumnMajorSparseMatrix zero(int rows, int columns, int capacity) { return CCSMatrix.zero(rows, columns, capacity); } /** * Creates a diagonal {@link ColumnMajorSparseMatrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static ColumnMajorSparseMatrix diagonal(int size, double diagonal) { return CCSMatrix.diagonal(size, diagonal); } /** * Creates an identity {@link ColumnMajorSparseMatrix} of the given {@code size}. */ public static ColumnMajorSparseMatrix identity(int size) { return CCSMatrix.identity(size); } /** * Creates a random {@link ColumnMajorSparseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static ColumnMajorSparseMatrix random(int rows, int columns, double density, Random random) { return CCSMatrix.random(rows, columns, density, random); } /** * Creates a random symmetric {@link ColumnMajorSparseMatrix} of the given {@code size}. */ public static ColumnMajorSparseMatrix randomSymmetric(int size, double density, Random random) { return CCSMatrix.randomSymmetric(size, density, random); } /** * Creates a new {@link ColumnMajorSparseMatrix} from the given 1D {@code array} with * compressing (copying) the underlying array. */ public static ColumnMajorSparseMatrix from1DArray(int rows, int columns, double[] array) { return CCSMatrix.from1DArray(rows, columns, array); } /** * Creates a new {@link ColumnMajorSparseMatrix} from the given 2D {@code array} with * compressing (copying) the underlying array. */ public static ColumnMajorSparseMatrix from2DArray(double[][] array) { return CCSMatrix.from2DArray(array); } /** * Creates a block {@link ColumnMajorSparseMatrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static ColumnMajorSparseMatrix block(Matrix a, Matrix b, Matrix c, Matrix d) { return CCSMatrix.block(a, b, c, d); } /** * Parses {@link ColumnMajorSparseMatrix} from the given CSV string. * * @param csv the CSV string representing a matrix * * @return a parsed matrix */ public static ColumnMajorSparseMatrix fromCSV(String csv) { return Matrix.fromCSV(csv).to(Matrices.SPARSE_COLUMN_MAJOR); } /** * Parses {@link ColumnMajorSparseMatrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static ColumnMajorSparseMatrix fromMatrixMarket(String mm) { return Matrix.fromMatrixMarket(mm).to(Matrices.SPARSE_COLUMN_MAJOR); } public ColumnMajorSparseMatrix(int rows, int columns) { super(rows, columns); } public ColumnMajorSparseMatrix(int rows, int columns, int cardinality) { super(rows, columns, cardinality); } @Override public boolean isRowMajor() { return false; } @Override public Matrix transpose() { Matrix result = RowMajorSparseMatrix.zero(columns, rows); MatrixIterator it = nonZeroColumnMajorIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(j, i, x); } return result; } @Override public Matrix rotate() { // TODO: it can be a bit faster Matrix result = RowMajorSparseMatrix.zero(columns, rows); MatrixIterator it = nonZeroColumnMajorIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(j, rows - 1 - i, x); } return result; } @Override public ColumnMajorMatrixIterator iterator() { return columnMajorIterator(); } @Override public MatrixIterator nonZeroIterator() { return nonZeroColumnMajorIterator(); } public abstract Iterator iteratorOrNonZeroColumns(); @Override public T apply(MatrixOperation operation) { operation.ensureApplicableTo(this); return operation.apply(this); } @Override public T apply(MatrixMatrixOperation operation, Matrix that) { return that.apply(operation.partiallyApply(this)); } @Override public T apply(MatrixVectorOperation operation, Vector that) { return that.apply(operation.partiallyApply(this)); } } la4j-0.6.0/src/main/java/org/la4j/matrix/DenseMatrix.java000066400000000000000000000134471263320764000230320ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.dense.Basic1DMatrix; import org.la4j.matrix.dense.Basic2DMatrix; import org.la4j.operation.MatrixMatrixOperation; import org.la4j.operation.MatrixOperation; import org.la4j.operation.MatrixVectorOperation; import org.la4j.Vector; import org.la4j.vector.DenseVector; import java.text.NumberFormat; import java.util.Random; public abstract class DenseMatrix extends Matrix { /** * Creates a zero {@link DenseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static DenseMatrix zero(int rows, int columns) { return Basic2DMatrix.zero(rows, columns); } /** * Creates a constant {@link DenseMatrix} of the given shape and {@code value}. */ public static DenseMatrix constant(int rows, int columns, double constant) { return Basic2DMatrix.constant(rows, columns, constant); } /** * Creates a diagonal {@link DenseMatrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static DenseMatrix diagonal(int size, double diagonal) { return Basic2DMatrix.diagonal(size, diagonal); } /** * Creates an unit {@link DenseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static DenseMatrix unit(int rows, int columns) { return Basic2DMatrix.unit(rows, columns); } /** * Creates an identity {@link DenseMatrix} of the given {@code size}. */ public static DenseMatrix identity(int size) { return Basic2DMatrix.identity(size); } /** * Creates a random {@link DenseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static DenseMatrix random(int rows, int columns, Random random) { return Basic2DMatrix.random(rows, columns, random); } /** * Creates a random symmetric {@link DenseMatrix} of the given {@code size}. */ public static DenseMatrix randomSymmetric(int size, Random random) { return Basic2DMatrix.randomSymmetric(size, random); } /** * Creates a {@link DenseMatrix} of the given 1D {@code array} w/o * copying the underlying array. */ public static DenseMatrix from1DArray(int rows, int columns, double[] array) { return Basic1DMatrix.from1DArray(rows, columns, array); } /** * Creates a {@link DenseMatrix} of the given 2D {@code array} w/o * copying the underlying array. */ public static DenseMatrix from2DArray(double[][] array) { return Basic2DMatrix.from2DArray(array); } /** * Creates a block {@link DenseMatrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static DenseMatrix block(Matrix a, Matrix b, Matrix c, Matrix d) { return Basic2DMatrix.block(a, b, c, d); } /** * Parses {@link DenseMatrix} from the given CSV string. * * @param csv the CSV string representing a matrix * * @return a parsed matrix */ public static DenseMatrix fromCSV(String csv) { return Matrix.fromCSV(csv).to(Matrices.DENSE); } /** * Parses {@link DenseMatrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static DenseMatrix fromMatrixMarket(String mm) { return Matrix.fromMatrixMarket(mm).to(Matrices.DENSE); } public DenseMatrix(int rows, int columns) { super(rows, columns); } /** * Converts this dense matrix to double array. * * @return an array representation of this matrix */ public abstract double[][] toArray(); @Override public Vector getRow(int i) { Vector result = DenseVector.zero(columns); for (int j = 0; j < columns; j++) { result.set(j, get(i, j)); } return result; } @Override public Vector getColumn(int j) { Vector result = DenseVector.zero(rows); for (int i = 0; i < rows; i++) { result.set(i, get(i, j)); } return result; } @Override public T apply(MatrixOperation operation) { operation.ensureApplicableTo(this); return operation.apply(this); } @Override public T apply(MatrixMatrixOperation operation, Matrix that) { return that.apply(operation.partiallyApply(this)); } @Override public T apply(MatrixVectorOperation operation, Vector that) { return that.apply(operation.partiallyApply(this)); } @Override public String toMatrixMarket(NumberFormat formatter) { StringBuilder out = new StringBuilder(); out.append("%%MatrixMarket matrix array real general\n"); out.append(rows).append(' ').append(columns).append('\n'); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { out.append(formatter.format(get(i, j))).append('\n'); } } return out.toString(); } } la4j-0.6.0/src/main/java/org/la4j/matrix/MatrixFactory.java000066400000000000000000000022131263320764000233700ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of the la4j project (http://la4j.org) * * 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. * * Contributor(s): */ package org.la4j.matrix; import org.la4j.Matrix; import java.lang.reflect.ParameterizedType; /** * An abstract matrix factory. * * @param */ public abstract class MatrixFactory { @SuppressWarnings("unchecked cast") public final Class outputClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; public abstract T apply(int rows, int columns); } la4j-0.6.0/src/main/java/org/la4j/matrix/RowMajorSparseMatrix.java000066400000000000000000000141731263320764000247070ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix; import org.la4j.Matrices; import org.la4j.iterator.MatrixIterator; import org.la4j.iterator.VectorIterator; import org.la4j.Matrix; import org.la4j.matrix.sparse.CRSMatrix; import org.la4j.operation.MatrixMatrixOperation; import org.la4j.operation.MatrixOperation; import org.la4j.operation.MatrixVectorOperation; import org.la4j.Vector; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Random; public abstract class RowMajorSparseMatrix extends SparseMatrix { /** * Creates a zero {@link RowMajorSparseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static RowMajorSparseMatrix zero(int rows, int columns) { return CRSMatrix.zero(rows, columns); } /** * Creates a zero {@link RowMajorSparseMatrix} of the given shape: * {@code rows} x {@code columns} with the given {@code capacity}. */ public static RowMajorSparseMatrix zero(int rows, int columns, int capacity) { return CRSMatrix.zero(rows, columns, capacity); } /** * Creates a diagonal {@link RowMajorSparseMatrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static RowMajorSparseMatrix diagonal(int size, double diagonal) { return CRSMatrix.diagonal(size, diagonal); } /** * Creates an identity {@link RowMajorSparseMatrix} of the given {@code size}. */ public static RowMajorSparseMatrix identity(int size) { return CRSMatrix.identity(size); } /** * Creates a random {@link RowMajorSparseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static RowMajorSparseMatrix random(int rows, int columns, double density, Random random) { return CRSMatrix.random(rows, columns, density, random); } /** * Creates a random symmetric {@link RowMajorSparseMatrix} of the given {@code size}. */ public static RowMajorSparseMatrix randomSymmetric(int size, double density, Random random) { return CRSMatrix.randomSymmetric(size, density, random); } /** * Creates a new {@link RowMajorSparseMatrix} from the given 1D {@code array} with * compressing (copying) the underlying array. */ public static RowMajorSparseMatrix from1DArray(int rows, int columns, double[] array) { return CRSMatrix.from1DArray(rows, columns, array); } /** * Creates a new {@link RowMajorSparseMatrix} from the given 2D {@code array} with * compressing (copying) the underlying array. */ public static RowMajorSparseMatrix from2DArray(double[][] array) { return CRSMatrix.from2DArray(array); } /** * Creates a block {@link RowMajorSparseMatrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static RowMajorSparseMatrix block(Matrix a, Matrix b, Matrix c, Matrix d) { return CRSMatrix.block(a, b, c, d); } /** * Parses {@link RowMajorSparseMatrix} from the given CSV string. * * @param csv the CSV string representing a matrix * * @return a parsed matrix */ public static RowMajorSparseMatrix fromCSV(String csv) { return Matrix.fromCSV(csv).to(Matrices.SPARSE_ROW_MAJOR); } /** * Parses {@link RowMajorSparseMatrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static RowMajorSparseMatrix fromMatrixMarket(String mm) { return Matrix.fromMatrixMarket(mm).to(Matrices.SPARSE_ROW_MAJOR); } public RowMajorSparseMatrix(int rows, int columns) { super(rows, columns); } public RowMajorSparseMatrix(int rows, int columns, int cardinality) { super(rows, columns, cardinality); } @Override public boolean isRowMajor() { return true; } @Override public Matrix transpose() { Matrix result = ColumnMajorSparseMatrix.zero(columns, rows); MatrixIterator it = nonZeroRowMajorIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(j, i, x); } return result; } @Override public Matrix rotate() { Matrix result = ColumnMajorSparseMatrix.zero(columns, rows); Iterator nzRows = iteratorOfNonZeroRows(); List reversedNzRows = new LinkedList(); while (nzRows.hasNext()) { reversedNzRows.add(0, nzRows.next()); } for (int i: reversedNzRows) { VectorIterator it = nonZeroIteratorOfRow(i); while (it.hasNext()) { double x = it.next(); int j = it.index(); result.set(j, rows - 1 - i, x); } } return result; } public abstract Iterator iteratorOfNonZeroRows(); @Override public T apply(MatrixOperation operation) { operation.ensureApplicableTo(this); return operation.apply(this); } @Override public T apply(MatrixMatrixOperation operation, Matrix that) { return that.apply(operation.partiallyApply(this)); } @Override public T apply(MatrixVectorOperation operation, Vector that) { return that.apply(operation.partiallyApply(this)); } } la4j-0.6.0/src/main/java/org/la4j/matrix/SparseMatrix.java000066400000000000000000000431201263320764000232200ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix; import org.la4j.iterator.ColumnMajorMatrixIterator; import org.la4j.iterator.MatrixIterator; import org.la4j.iterator.RowMajorMatrixIterator; import org.la4j.iterator.VectorIterator; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.functor.MatrixAccumulator; import org.la4j.matrix.functor.MatrixProcedure; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.matrix.sparse.CCSMatrix; import org.la4j.matrix.sparse.CRSMatrix; import org.la4j.vector.functor.VectorAccumulator; import org.la4j.vector.functor.VectorProcedure; import org.la4j.vector.SparseVector; import java.text.NumberFormat; import java.util.Random; public abstract class SparseMatrix extends Matrix { /** * Creates a zero {@link SparseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static SparseMatrix zero(int rows, int columns) { return CCSMatrix.zero(rows, columns); } /** * Creates a zero {@link SparseMatrix} of the given shape: * {@code rows} x {@code columns} with the given {@code capacity}. */ public static SparseMatrix zero(int rows, int columns, int capacity) { return CRSMatrix.zero(rows, columns, capacity); } /** * Creates a diagonal {@link SparseMatrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static SparseMatrix diagonal(int size, double diagonal) { return CRSMatrix.diagonal(size, diagonal); } /** * Creates an identity {@link SparseMatrix} of the given {@code size}. */ public static SparseMatrix identity(int size) { return CRSMatrix.identity(size); } /** * Creates a random {@link SparseMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static SparseMatrix random(int rows, int columns, double density, Random random) { return CRSMatrix.random(rows, columns, density, random); } /** * Creates a random symmetric {@link SparseMatrix} of the given {@code size}. */ public static SparseMatrix randomSymmetric(int size, double density, Random random) { return CRSMatrix.randomSymmetric(size, density, random); } /** * Creates a new {@link SparseMatrix} from the given 1D {@code array} with * compressing (copying) the underlying array. */ public static SparseMatrix from1DArray(int rows, int columns, double[] array) { return CRSMatrix.from1DArray(rows, columns, array); } /** * Creates a new {@link SparseMatrix} from the given 2D {@code array} with * compressing (copying) the underlying array. */ public static SparseMatrix from2DArray(double[][] array) { return CRSMatrix.from2DArray(array); } /** * Creates a block {@link SparseMatrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static SparseMatrix block(Matrix a, Matrix b, Matrix c, Matrix d) { return CRSMatrix.block(a, b, c, d); } /** * Parses {@link SparseMatrix} from the given CSV string. * * @param csv the CSV string representing a matrix * * @return a parsed matrix */ public static SparseMatrix fromCSV(String csv) { return Matrix.fromCSV(csv).to(Matrices.SPARSE); } /** * Parses {@link SparseMatrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static SparseMatrix fromMatrixMarket(String mm) { return Matrix.fromMatrixMarket(mm).to(Matrices.SPARSE); } protected int cardinality; public SparseMatrix(int rows, int columns) { this(rows, columns, 0); } public SparseMatrix(int rows, int columns, int cardinality) { super(rows, columns); this.cardinality = cardinality; } @Override public double get(int i, int j) { return getOrElse(i, j, 0.0); } /** * Gets the specified element, or a {@code defaultValue} if there * is no actual element at ({@code i}, {@code j}) in this sparse matrix. * * @param i the element's row index * @param j the element's column index * @param defaultValue the default value * * @return the element of this vector or a default value */ public abstract double getOrElse(int i, int j, double defaultValue); /** * Checks whether or not this sparse matrix row-major. */ public abstract boolean isRowMajor(); public boolean isColumnMajor() { return !isRowMajor(); } /** * Returns the cardinality (the number of non-zero elements) * of this sparse matrix. * * @return the cardinality of this matrix */ public int cardinality() { return cardinality; } /** * Returns the density (non-zero elements divided by total elements) * of this sparse matrix. * * @return the density of this matrix */ public double density() { return cardinality / (double) (rows * columns); } /** * @return a capacity of this sparse matrix */ protected long capacity() { return ((long) rows) * columns; } @Override public Vector getRow(int i) { Vector result = SparseVector.zero(columns); VectorIterator it = nonZeroIteratorOfRow(i); while (it.hasNext()) { double x = it.next(); int j = it.index(); result.set(j, x); } return result; } @Override public Vector getColumn(int j) { Vector result = SparseVector.zero(rows); VectorIterator it = nonZeroIteratorOfColumn(j); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, x); } return result; } @Override public Matrix multiply(double value) { MatrixIterator it = nonZeroIterator(); Matrix result = blank(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, x * value); } return result; } @Override public Matrix add(double value) { MatrixIterator it = nonZeroIterator(); Matrix result = DenseMatrix.constant(rows, columns, value); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, x + value); } return result; } /** * Whether or not the specified element is zero. * * @param i element's row index * @param j element's column index * * @return {@code true} if specified element is zero, {@code false} otherwise */ public boolean isZeroAt(int i, int j) { return !nonZeroAt(i, j); } /** * Whether or not the specified element is not zero. * * @param i element's row index * @param j element's column index * * @return {@code true} if specified element is not zero, {@code false} otherwise */ public abstract boolean nonZeroAt(int i, int j); /** * Applies given {@code procedure} to each non-zero element of this matrix. * * @param procedure the matrix procedure */ public void eachNonZero(MatrixProcedure procedure) { MatrixIterator it = nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); procedure.apply(i, j, x); } } /** * Applies the given {@code procedure} to each non-zero element of the specified row of this matrix. * * @param i the row index. * @param procedure the {@link VectorProcedure}. */ public void eachNonZeroInRow(int i, VectorProcedure procedure) { VectorIterator it = nonZeroIteratorOfRow(i); while (it.hasNext()) { double x = it.next(); int j = it.index(); procedure.apply(j, x); } } /** * Applies the given {@code procedure} to each non-zero element of the specified column of this matrix. * * @param j the column index. * @param procedure the {@link VectorProcedure}. */ public void eachNonZeroInColumn(int j, VectorProcedure procedure) { VectorIterator it = nonZeroIteratorOfColumn(j); while (it.hasNext()) { double x = it.next(); int i = it.index(); procedure.apply(i, x); } } /** * Folds non-zero elements of this matrix with given {@code accumulator}. * * @param accumulator the matrix accumulator * * @return the accumulated value */ public double foldNonZero(MatrixAccumulator accumulator) { eachNonZero(Matrices.asAccumulatorProcedure(accumulator)); return accumulator.accumulate(); } /** * Folds non-zero elements of the specified row in this matrix with the given {@code accumulator}. * * @param i the row index. * @param accumulator the {@link VectorAccumulator}. * * @return the accumulated value. */ public double foldNonZeroInRow(int i, VectorAccumulator accumulator) { eachNonZeroInRow(i, Vectors.asAccumulatorProcedure(accumulator)); return accumulator.accumulate(); } /** * Folds non-zero elements of the specified column in this matrix with the given {@code accumulator}. * * @param j the column index. * @param accumulator the {@link VectorAccumulator}. * * @return the accumulated value. */ public double foldNonZeroInColumn(int j, VectorAccumulator accumulator) { eachNonZeroInColumn(j, Vectors.asAccumulatorProcedure(accumulator)); return accumulator.accumulate(); } /** * Folds non-zero elements (in a column-by-column manner) of this matrix with given {@code accumulator}. * * @param accumulator the matrix accumulator * * @return the accumulated vector */ public double[] foldNonZeroInColumns(VectorAccumulator accumulator) { double[] result = new double[columns]; for (int j = 0; j < columns; j++) { result[j] = foldNonZeroInColumn(j, accumulator); } return result; } /** * Folds non-zero elements (in a row-by-row manner) of this matrix with given {@code accumulator}. * * @param accumulator the matrix accumulator * * @return the accumulated vector */ public double[] foldNonZeroInRows(VectorAccumulator accumulator) { double[] result = new double[rows]; for (int i = 0; i < rows; i++) { result[i] = foldNonZeroInRow(i, accumulator); } return result; } /** * Returns a non-zero matrix iterator. * * @return a non-zero matrix iterator */ public MatrixIterator nonZeroIterator() { return nonZeroRowMajorIterator(); } /** * Returns a non-zero row-major matrix iterator. * * @return a non-zero row-major matrix iterator. */ public RowMajorMatrixIterator nonZeroRowMajorIterator() { return new RowMajorMatrixIterator(rows, columns) { private long limit = (long) rows * columns; private long i = -1; @Override public int rowIndex() { return (int) (i / columns); } @Override public int columnIndex() { return (int) (i - ((i / columns) * columns)); } @Override public double get() { return SparseMatrix.this.get(rowIndex(), columnIndex()); } @Override public void set(double value) { SparseMatrix.this.set(rowIndex(), columnIndex(), value); } @Override public boolean hasNext() { while (i + 1 < limit) { i++; if (SparseMatrix.this.nonZeroAt(rowIndex(), columnIndex())) { i--; break; } } return i + 1 < limit; } @Override public Double next() { i++; return get(); } }; } /** * Returns a non-zero column-major matrix iterator. * * @return a non-zero column major matrix iterator. */ public ColumnMajorMatrixIterator nonZeroColumnMajorIterator() { return new ColumnMajorMatrixIterator(rows, columns) { private long limit = (long) rows * columns; private long i = -1; @Override public int rowIndex() { return (int) (i - ((i / rows) * rows)); } @Override public int columnIndex() { return (int) (i / rows); } @Override public double get() { return SparseMatrix.this.get(rowIndex(), columnIndex()); } @Override public void set(double value) { SparseMatrix.this.set(rowIndex(), columnIndex(), value); } @Override public boolean hasNext() { while (i + 1 < limit) { i++; if (SparseMatrix.this.nonZeroAt(rowIndex(), columnIndex())) { i--; break; } } return i + 1 < limit; } @Override public Double next() { i++; return get(); } }; } /** * Returns a non-zero vector iterator of the given row {@code i}. * * @return a non-zero vector iterator */ public VectorIterator nonZeroIteratorOfRow(int i) { final int ii = i; return new VectorIterator(columns) { private int j = -1; @Override public int index() { return j; } @Override public double get() { return SparseMatrix.this.get(ii, j); } @Override public void set(double value) { SparseMatrix.this.set(ii, j, value); } @Override public boolean hasNext() { while (j + 1 < columns && SparseMatrix.this.isZeroAt(ii, j + 1)) { j++; } return j + 1 < columns; } @Override public Double next() { j++; return get(); } }; } /** * Returns a non-zero vector iterator of the given column {@code j}. * * @return a non-zero vector iterator */ public VectorIterator nonZeroIteratorOfColumn(int j) { final int jj = j; return new VectorIterator(rows) { private int i = -1; @Override public int index() { return i; } @Override public double get() { return SparseMatrix.this.get(i, jj); } @Override public void set(double value) { SparseMatrix.this.set(i, jj, value); } @Override public boolean hasNext() { while (i + 1 < rows && SparseMatrix.this.isZeroAt(i + 1, jj)) { i++; } return i + 1 < rows; } @Override public Double next() { i++; return get(); } }; } @Override public String toMatrixMarket(NumberFormat formatter) { String majority = isRowMajor() ? "row-major" : "column-major"; StringBuilder out = new StringBuilder(); MatrixIterator it = nonZeroIterator(); out.append("%%MatrixMarket matrix coordinate real general ") .append(majority).append('\n'); out.append(rows).append(' ').append(columns).append(' ') .append(cardinality).append('\n'); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); out.append(i + 1).append(' ').append(j + 1).append(' ') .append(formatter.format(x)).append('\n'); } return out.toString(); } protected void ensureCardinalityIsCorrect(long rows, long columns, long cardinality) { if (cardinality < 0) { fail("Cardinality should be positive: " + cardinality + "."); } long capacity = capacity(); if (cardinality > capacity) { fail("Cardinality should be less then or equal to capacity: " + capacity + "."); } } } la4j-0.6.0/src/main/java/org/la4j/matrix/dense/000077500000000000000000000000001263320764000210315ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/matrix/dense/Basic1DMatrix.java000066400000000000000000000246761263320764000243060ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Wajdy Essam * */ package org.la4j.matrix.dense; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Random; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.MatrixFactory; import org.la4j.Vector; import org.la4j.vector.dense.BasicVector; public class Basic1DMatrix extends DenseMatrix { private static final byte MATRIX_TAG = (byte) 0x00; /** * Creates a zero {@link Basic1DMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static Basic1DMatrix zero(int rows, int columns) { return new Basic1DMatrix(rows, columns); } /** * Creates a constant {@link Basic1DMatrix} of the given shape and {@code value}. */ public static Basic1DMatrix constant(int rows, int columns, double constant) { double array[] = new double[rows * columns]; Arrays.fill(array, constant); return new Basic1DMatrix(rows, columns, array); } /** * Creates a diagonal {@link Basic1DMatrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static Basic1DMatrix diagonal(int size, double diagonal) { double array[] = new double[size * size]; for (int i = 0; i < size; i++) { array[i * size + i] = diagonal; } return new Basic1DMatrix(size, size, array); } /** * Creates an unit {@link Basic1DMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static Basic1DMatrix unit(int rows, int columns) { return Basic1DMatrix.constant(rows, columns, 1.0); } /** * Creates an identity {@link Basic1DMatrix} of the given {@code size}. */ public static Basic1DMatrix identity(int size) { return Basic1DMatrix.diagonal(size, 1.0); } /** * Creates a random {@link Basic1DMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static Basic1DMatrix random(int rows, int columns, Random random) { double array[] = new double[rows * columns]; for (int i = 0; i < rows * columns; i++) { array[i] = random.nextDouble(); } return new Basic1DMatrix(rows, columns, array); } /** * Creates a random symmetric {@link Basic1DMatrix} of the given {@code size}. */ public static Basic1DMatrix randomSymmetric(int size, Random random) { double array[] = new double[size * size]; for (int i = 0; i < size; i++) { for (int j = i; j < size; j++) { double value = random.nextDouble(); array[i * size + j] = value; array[j * size + i] = value; } } return new Basic1DMatrix(size, size, array); } /** * Creates a {@link Basic1DMatrix} of the given 1D {@code array} w/o * copying the underlying array. */ public static Basic1DMatrix from1DArray(int rows, int columns, double[] array) { return new Basic1DMatrix(rows, columns, array); } /** * Creates a {@link Basic1DMatrix} of the given 2D {@code array} with * copying the underlying array. */ public static Basic1DMatrix from2DArray(double[][] array) { int rows = array.length; int columns = array[0].length; double[] array1D = new double[rows * columns]; int offset = 0; for (int i = 0; i < rows; i++) { System.arraycopy(array[i], 0, array1D, offset, columns); offset += columns; } return new Basic1DMatrix(rows, columns, array1D); } /** * Creates a block {@link Basic1DMatrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static Basic1DMatrix block(Matrix a, Matrix b, Matrix c, Matrix d) { if ((a.rows() != b.rows()) || (a.columns() != c.columns()) || (c.rows() != d.rows()) || (b.columns() != d.columns())) { throw new IllegalArgumentException("Sides of blocks are incompatible!"); } int rows = a.rows() + c.rows(), columns = a.columns() + b.columns(); double array[] = new double[rows * columns]; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if ((i < a.rows()) && (j < a.columns())) { array[i * rows + j] = a.get(i, j); } if ((i < a.rows()) && (j > a.columns())) { array[i * rows + j] = b.get(i, j); } if ((i > a.rows()) && (j < a.columns())) { array[i * rows + j] = c.get(i, j); } if ((i > a.rows()) && (j > a.columns())) { array[i * rows + j] = d.get(i, j); } } } return new Basic1DMatrix(rows, columns, array); } /** * Decodes {@link Basic1DMatrix} from the given byte {@code array}. * * @param array the byte array representing a matrix * * @return a decoded matrix */ public static Basic1DMatrix fromBinary(byte[] array) { ByteBuffer buffer = ByteBuffer.wrap(array); if (buffer.get() != MATRIX_TAG) { throw new IllegalArgumentException("Can not decode Basic1DMatrix from the given byte array."); } int rows = buffer.getInt(); int columns = buffer.getInt(); int capacity = rows * columns; double[] values = new double[capacity]; for (int i = 0; i < capacity; i++) { values[i] = buffer.getDouble(); } return new Basic1DMatrix(rows, columns, values); } /** * Parses {@link Basic1DMatrix} from the given CSV string. * * @param csv the CSV string representing a matrix * * @return a parsed matrix */ public static Basic1DMatrix fromCSV(String csv) { return Matrix.fromCSV(csv).to(Matrices.BASIC_1D); } /** * Parses {@link Basic1DMatrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static Basic1DMatrix fromMatrixMarket(String mm) { return Matrix.fromMatrixMarket(mm).to(Matrices.BASIC_1D); } private double self[]; public Basic1DMatrix() { this(0, 0); } public Basic1DMatrix(int rows, int columns) { this(rows, columns, new double[rows * columns]); } public Basic1DMatrix(int rows, int columns, double array[]) { super(rows, columns); this.self = array; } @Override public double get(int i, int j) { ensureIndexesAreInBounds(i, j); return self[i * columns + j]; } @Override public void set(int i, int j, double value) { ensureIndexesAreInBounds(i, j); self[i * columns + j] = value; } @Override public void setAll(double value) { Arrays.fill(self, value); } @Override public void swapRows(int i, int j) { if (i != j) { for (int k = 0; k < columns; k++) { double tmp = self[i * columns + k]; self[i * columns + k] = self[j * columns + k]; self[j * columns + k] = tmp; } } } @Override public void swapColumns(int i, int j) { if (i != j) { for (int k = 0; k < rows; k++) { double tmp = self[k * columns + i]; self[k * columns + i] = self[k * columns + j]; self[k * columns + j] = tmp; } } } @Override public Vector getRow(int i) { double result[] = new double[columns]; System.arraycopy(self, i * columns , result, 0, columns); return new BasicVector(result); } @Override public Matrix copyOfShape(int rows, int columns) { ensureDimensionsAreCorrect(rows, columns); if (this.rows < rows && this.columns == columns) { double $self[] = new double[rows * columns]; System.arraycopy(self, 0, $self, 0, this.rows * columns); return new Basic1DMatrix(rows, columns, $self); } double[] $self = new double[rows * columns]; int columnSize = columns < this.columns ? columns : this.columns; int rowSize = rows < this.rows ? rows : this.rows; for (int i = 0; i < rowSize; i++) { System.arraycopy(self, i * this.columns, $self, i * columns, columnSize); } return new Basic1DMatrix(rows, columns, $self); } @Override public double[][] toArray() { double result[][] = new double[rows][columns]; int offset = 0; for (int i = 0; i < rows; i++) { System.arraycopy(self, offset, result[i], 0, columns); offset += columns; } return result; } @Override public T to(MatrixFactory factory) { if (factory.outputClass == Basic1DMatrix.class) { return factory.outputClass.cast(this); } return super.to(factory); } @Override public Matrix blankOfShape(int rows, int columns) { return Basic1DMatrix.zero(rows, columns); } @Override public byte[] toBinary() { int size = 1 + // 1 byte: class tag 4 + // 4 bytes: rows 4 + // 4 bytes: columns (8 * rows * columns); // 8 * rows * columns bytes: values ByteBuffer buffer = ByteBuffer.allocate(size); buffer.put(MATRIX_TAG); buffer.putInt(rows); buffer.putInt(columns); for (double value: self) { buffer.putDouble(value); } return buffer.array(); } } la4j-0.6.0/src/main/java/org/la4j/matrix/dense/Basic2DMatrix.java000066400000000000000000000232761263320764000243020ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.dense; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Random; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.MatrixFactory; import org.la4j.Vector; import org.la4j.vector.dense.BasicVector; public class Basic2DMatrix extends DenseMatrix { private static final byte MATRIX_TAG = (byte) 0x10; /** * Creates a zero {@link Basic2DMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static Basic2DMatrix zero(int rows, int columns) { return new Basic2DMatrix(rows, columns); } /** * Creates a constant {@link Basic2DMatrix} of the given shape and {@code value}. */ public static Basic2DMatrix constant(int rows, int columns, double constant) { double array[][] = new double[rows][columns]; for (int i = 0; i < rows; i++) { Arrays.fill(array[i], constant); } return new Basic2DMatrix(array); } /** * Creates a diagonal {@link Basic2DMatrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static Basic2DMatrix diagonal(int size, double diagonal) { double array[][] = new double[size][size]; for (int i = 0; i < size; i++) { array[i][i] = diagonal; } return new Basic2DMatrix(array); } /** * Creates an unit {@link Basic2DMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static Basic2DMatrix unit(int rows, int columns) { return Basic2DMatrix.constant(rows, columns, 1.0); } /** * Creates an identity {@link Basic2DMatrix} of the given {@code size}. */ public static Basic2DMatrix identity(int size) { return Basic2DMatrix.diagonal(size, 1.0); } /** * Creates a random {@link Basic2DMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static Basic2DMatrix random(int rows, int columns, Random random) { double array[][] = new double[rows][columns]; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { array[i][j] = random.nextDouble(); } } return new Basic2DMatrix(array); } /** * Creates a random symmetric {@link Basic2DMatrix} of the given {@code size}. */ public static Basic2DMatrix randomSymmetric(int size, Random random) { double array[][] = new double[size][size]; for (int i = 0; i < size; i++) { for (int j = i; j < size; j++) { double value = random.nextDouble(); array[i][j] = value; array[j][i] = value; } } return new Basic2DMatrix(array); } /** * Creates a {@link Basic2DMatrix} of the given 1D {@code array} with * copying the underlying array. */ public static Basic2DMatrix from1DArray(int rows, int columns, double[] array) { double[][] array2D = new double[rows][columns]; for (int i = 0; i < rows; i++) { System.arraycopy(array, i * columns, array2D[i], 0, columns); } return new Basic2DMatrix(array2D); } /** * Creates a {@link Basic2DMatrix} of the given 2D {@code array} w/o * copying the underlying array. */ public static Basic2DMatrix from2DArray(double[][] array) { return new Basic2DMatrix(array); } /** * Creates a block {@link Basic2DMatrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static Basic2DMatrix block(Matrix a, Matrix b, Matrix c, Matrix d) { if ((a.rows() != b.rows()) || (a.columns() != c.columns()) || (c.rows() != d.rows()) || (b.columns() != d.columns())) { throw new IllegalArgumentException("Sides of blocks are incompatible!"); } int rows = a.rows() + c.rows(), columns = a.columns() + b.columns(); double array[][] = new double[rows][columns]; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if ((i < a.rows()) && (j < a.columns())) { array[i][j] = a.get(i, j); } if ((i < a.rows()) && (j > a.columns())) { array[i][j] = b.get(i, j); } if ((i > a.rows()) && (j < a.columns())) { array[i][j] = c.get(i, j); } if ((i > a.rows()) && (j > a.columns())) { array[i][j] = d.get(i, j); } } } return new Basic2DMatrix(array); } /** * Decodes {@link Basic2DMatrix} from the given byte {@code array}. * * @param array the byte array representing a matrix * * @return a decoded matrix */ public static Basic2DMatrix fromBinary(byte[] array) { ByteBuffer buffer = ByteBuffer.wrap(array); if (buffer.get() != MATRIX_TAG) { throw new IllegalArgumentException("Can not decode Basic2DMatrix from the given byte array."); } int rows = buffer.getInt(); int columns = buffer.getInt(); double[][] values = new double[rows][columns]; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { values[i][j] = buffer.getDouble(); } } return new Basic2DMatrix(values); } /** * Parses {@link Basic2DMatrix} from the given CSV string. * * @param csv the CSV string representing a matrix * * @return a parsed matrix */ public static Basic2DMatrix fromCSV(String csv) { return Matrix.fromCSV(csv).to(Matrices.BASIC_2D); } /** * Parses {@link Basic2DMatrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static Basic2DMatrix fromMatrixMarket(String mm) { return Matrix.fromMatrixMarket(mm).to(Matrices.BASIC_2D); } private double self[][]; public Basic2DMatrix() { this(0, 0); } public Basic2DMatrix(int rows, int columns) { this(new double[rows][columns]); } public Basic2DMatrix(double array[][]) { super(array.length, array.length == 0 ? 0: array[0].length); this.self = array; } @Override public double get(int i, int j) { return self[i][j]; } @Override public void set(int i, int j, double value) { self[i][j] = value; } @Override public void setAll(double value) { for (int i = 0; i < rows; i++) { Arrays.fill(self[i], value); } } @Override public void swapRows(int i, int j) { if (i != j) { double tmp[] = self[i]; self[i] = self[j]; self[j] = tmp; } } @Override public void swapColumns(int i, int j) { if (i != j) { for (int ii = 0; ii < rows; ii++) { double tmp = self[ii][i]; self[ii][i] = self[ii][j]; self[ii][j] = tmp; } } } @Override public Vector getRow(int i) { double result[] = new double[columns]; System.arraycopy(self[i], 0, result, 0, columns); return new BasicVector(result); } @Override public Matrix copyOfShape(int rows, int columns) { ensureDimensionsAreCorrect(rows, columns); double $self[][] = new double[rows][columns]; for (int i = 0; i < Math.min(this.rows, rows); i++) { System.arraycopy(self[i], 0, $self[i], 0, Math.min(this.columns, columns)); } return new Basic2DMatrix($self); } @Override public double[][] toArray() { double result[][] = new double[rows][columns]; for (int i = 0; i < rows; i++) { System.arraycopy(self[i], 0, result[i], 0, columns); } return result; } @Override public T to(MatrixFactory factory) { if (factory.outputClass == Basic2DMatrix.class) { return factory.outputClass.cast(this); } return super.to(factory); } @Override public Matrix blankOfShape(int rows, int columns) { return Basic2DMatrix.zero(rows, columns); } @Override public byte[] toBinary() { int size = 1 + // 1 byte: class tag 4 + // 4 bytes: rows 4 + // 4 bytes: columns (8 * rows * columns); // 8 * rows * columns bytes: values ByteBuffer buffer = ByteBuffer.allocate(size); buffer.put(MATRIX_TAG); buffer.putInt(rows); buffer.putInt(columns); for (int i = 0; i < rows; i++) { for (double value : self[i]) { buffer.putDouble(value); } } return buffer.array(); } } la4j-0.6.0/src/main/java/org/la4j/matrix/functor/000077500000000000000000000000001263320764000214135ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/matrix/functor/AdvancedMatrixPredicate.java000066400000000000000000000021331263320764000267700ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.functor; import org.la4j.Matrix; /** * An advanced matrix predicate that test the whole matrix rather than its * elements. */ public interface AdvancedMatrixPredicate { /** * Tests given {@code matrix}. * * @param matrix the source matrix * * @return whether the matrix meets this predicate */ boolean test(Matrix matrix); } la4j-0.6.0/src/main/java/org/la4j/matrix/functor/MatrixAccumulator.java000066400000000000000000000023631263320764000257260ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.functor; /** * A matrix accumulator that accumulates elements across matrix. */ public interface MatrixAccumulator { /** * Updates a value that was accumulated so far with new matrix element. * * @param i the row index * @param j the column index * @param value the element's value */ void update(int i, int j, double value); /** * Return the accumulated value and resets this accumulator. * * @return an accumulated value */ double accumulate(); } la4j-0.6.0/src/main/java/org/la4j/matrix/functor/MatrixFunction.java000066400000000000000000000021741263320764000252340ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.functor; /** * A matrix function that takes an element with its indices and produces * a new value. */ public interface MatrixFunction { /** * Evaluates a specified element. * * @param i the row index * @param j the column index * @param value the element's value * * @return a new element's value */ double evaluate(int i, int j, double value); } la4j-0.6.0/src/main/java/org/la4j/matrix/functor/MatrixPredicate.java000066400000000000000000000025521263320764000253470ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.functor; /** * A matrix predicate that tests each matrix element. */ public interface MatrixPredicate { /** * Tests number of rows and columns in the matrix. * * @param rows the number of rows * @param columns the number of columns * * @return whether the shape meets this predicate */ boolean test(int rows, int columns); /** * Tests matrix element. * * @param i the row index * @param j the column index * @param value the element's value * * @return whether the element meets this predicate */ boolean test(int i, int j, double value); } la4j-0.6.0/src/main/java/org/la4j/matrix/functor/MatrixProcedure.java000066400000000000000000000020631263320764000253740ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.functor; /** * A matrix procedure that performs an action of every matrix element. * */ public interface MatrixProcedure { /** * Acts on a matrix element. * * @param i the row index * @param j the columns * @param value the element's value */ void apply(int i, int j, double value); } la4j-0.6.0/src/main/java/org/la4j/matrix/sparse/000077500000000000000000000000001263320764000212305ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/matrix/sparse/CCSMatrix.java000066400000000000000000000751661263320764000237070ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Chandler May * Maxim Samoylov * Anveshi Charuvaka * Clement Skau * Catherine da Graca * */ package org.la4j.matrix.sparse; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.Random; import org.la4j.iterator.ColumnMajorMatrixIterator; import org.la4j.iterator.VectorIterator; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.MatrixFactory; import org.la4j.matrix.functor.MatrixFunction; import org.la4j.matrix.functor.MatrixProcedure; import org.la4j.Vector; import org.la4j.vector.functor.VectorProcedure; import org.la4j.vector.sparse.CompressedVector; /** * This is a CCS (Compressed Column Storage) matrix class. */ public class CCSMatrix extends ColumnMajorSparseMatrix { private static final byte MATRIX_TAG = (byte) 0x30; /** * Creates a zero {@link CCSMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static CCSMatrix zero(int rows, int columns) { return new CCSMatrix(rows, columns); } /** * Creates a zero {@link CCSMatrix} of the given shape: * {@code rows} x {@code columns} with the given {@code capacity}. */ public static CCSMatrix zero(int rows, int columns, int capacity) { return new CCSMatrix(rows, columns, capacity); } /** * Creates a diagonal {@link CCSMatrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static CCSMatrix diagonal(int size, double diagonal) { double values[] = new double[size]; int rowIndices[] = new int[size]; int columnPointers[] = new int[size + 1]; for (int i = 0; i < size; i++) { rowIndices[i] = i; columnPointers[i] = i; values[i] = diagonal; } columnPointers[size] = size; return new CCSMatrix(size, size, size, values, rowIndices, columnPointers); } /** * Creates an identity {@link CCSMatrix} of the given {@code size}. */ public static CCSMatrix identity(int size) { return CCSMatrix.diagonal(size, 1.0); } /** * Creates a random {@link CCSMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static CCSMatrix random(int rows, int columns, double density, Random random) { if (density < 0.0 || density > 1.0) { throw new IllegalArgumentException("The density value should be between 0 and 1.0"); } int cardinality = Math.max((int)((rows * columns) * density), columns); double values[] = new double[cardinality]; int rowIndices[] = new int[cardinality]; int columnPointers[] = new int[columns + 1]; int kk = cardinality / columns; int indices[] = new int[kk]; int k = 0; for (int j = 0; j < columns; j++) { columnPointers[j] = k; for (int jj = 0; jj < kk; jj++) { indices[jj] = random.nextInt(rows); } Arrays.sort(indices); int previous = -1; for (int jj = 0; jj < kk; jj++) { if (indices[jj] == previous) { continue; } values[k] = random.nextDouble(); rowIndices[k++] = indices[jj]; previous = indices[jj]; } } columnPointers[columns] = cardinality; return new CCSMatrix(rows, columns, cardinality, values, rowIndices, columnPointers); } /** * Creates a random symmetric {@link CCSMatrix} of the given {@code size}. */ public static CCSMatrix randomSymmetric(int size, double density, Random random) { int cardinality = (int) ((size * size) * density); // TODO: Issue 15 // We can do better here. All we need to is to make sure // that all the writes to CCS matrix are done in a serial // order (column-major). This will give us O(1) performance // per write. CCSMatrix matrix = new CCSMatrix(size, size, cardinality); for (int k = 0; k < cardinality / 2; k++) { int i = random.nextInt(size); int j = random.nextInt(size); double value = random.nextDouble(); matrix.set(i, j, value); matrix.set(j, i, value); } return matrix; } /** * Creates a new {@link CCSMatrix} from the given 1D {@code array} with * compressing (copying) the underlying array. */ public static CCSMatrix from1DArray(int rows, int columns, double[] array) { CCSMatrix result = CCSMatrix.zero(rows, columns); for (int j = 0; j < columns; j++) { for (int i = 0; i < rows; i++) { int k = i * columns + j; if (array[k] != 0.0) { result.set(i, j, array[k]); } } } return result; } /** * Creates a new {@link CCSMatrix} from the given 2D {@code array} with * compressing (copying) the underlying array. */ public static CCSMatrix from2DArray(double[][] array) { int rows = array.length; int columns = array[0].length; CCSMatrix result = CCSMatrix.zero(rows, columns); for (int j = 0; j < columns; j++) { for (int i = 0; i < rows; i++) { if (array[i][j] != 0.0) { result.set(i, j, array[i][j]); } } } return result; } /** * Creates a block {@link CCSMatrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static CCSMatrix block(Matrix a, Matrix b, Matrix c, Matrix d) { if ((a.rows() != b.rows()) || (a.columns() != c.columns()) || (c.rows() != d.rows()) || (b.columns() != d.columns())) { throw new IllegalArgumentException("Sides of blocks are incompatible!"); } int rows = a.rows() + c.rows(), columns = a.columns() + b.columns(); ArrayList values = new ArrayList(); ArrayList rowIndices = new ArrayList(); int columnPointers[] = new int[rows + 1]; int k = 0; columnPointers[0] = 0; double current = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if ((i < a.rows()) && (j < a.columns())) { current = a.get(i, j); } if ((i < a.rows()) && (j > a.columns())) { current = b.get(i, j); } if ((i > a.rows()) && (j < a.columns())) { current = c.get(i, j); } if ((i > a.rows()) && (j > a.columns())) { current = d.get(i, j); } if (Math.abs(current) > Matrices.EPS) { values.add(current); rowIndices.add(j); k++; } } columnPointers[i + 1] = k; } double valuesArray[] = new double[values.size()]; int rowIndArray[] = new int[rowIndices.size()]; for (int i = 0; i < values.size(); i++) { valuesArray[i] = values.get(i); rowIndArray[i] = rowIndices.get(i); } return new CCSMatrix(rows, columns, k, valuesArray, rowIndArray, columnPointers); } /** * Decodes {@link CCSMatrix} from the given byte {@code array}. * * @param array the byte array representing a matrix * * @return a decoded matrix */ public static CCSMatrix fromBinary(byte[] array) { ByteBuffer buffer = ByteBuffer.wrap(array); if (buffer.get() != MATRIX_TAG) { throw new IllegalArgumentException("Can not decode CCSMatrix from the given byte array."); } int rows = buffer.getInt(); int columns = buffer.getInt(); int cardinality = buffer.getInt(); int[] rowIndices = new int[cardinality]; double[] values = new double[cardinality]; int[] columnsPointers = new int[columns + 1]; for (int i = 0; i < cardinality; i++) { rowIndices[i] = buffer.getInt(); values[i] = buffer.getDouble(); } for (int i = 0; i < columns + 1; i++) { columnsPointers[i] = buffer.getInt(); } return new CCSMatrix(rows, columns, cardinality, values, rowIndices, columnsPointers); } /** * Parses {@link CCSMatrix} from the given CSV string. * * @param csv the CSV string representing a matrix * * @return a parsed matrix */ public static CCSMatrix fromCSV(String csv) { return Matrix.fromCSV(csv).to(Matrices.CCS); } /** * Parses {@link CCSMatrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static CCSMatrix fromMatrixMarket(String mm) { return Matrix.fromMatrixMarket(mm).to(Matrices.CCS); } private static final int MINIMUM_SIZE = 32; private double values[]; private int rowIndices[]; private int columnPointers[]; public CCSMatrix() { this(0, 0); } public CCSMatrix(int rows, int columns) { this (rows, columns, 0); } public CCSMatrix(int rows, int columns, int capacity) { super(rows, columns); ensureCardinalityIsCorrect(rows, columns, capacity); int alignedSize = align(capacity); this.values = new double[alignedSize]; this.rowIndices = new int[alignedSize]; this.columnPointers = new int[columns + 1]; } public CCSMatrix(int rows, int columns, int cardinality, double values[], int rowIndices[], int columnPointers[]) { super(rows, columns, cardinality); ensureCardinalityIsCorrect(rows, columns, cardinality); this.values = values; this.rowIndices = rowIndices; this.columnPointers = columnPointers; } @Override public double getOrElse(int i, int j, double defaultValue) { ensureIndexesAreInBounds(i, j); int k = searchForRowIndex(i, columnPointers[j], columnPointers[j + 1]); if (k < columnPointers[j + 1] && rowIndices[k] == i) { return values[k]; } return defaultValue; } @Override public void set(int i, int j, double value) { ensureIndexesAreInBounds(i, j); int k = searchForRowIndex(i, columnPointers[j], columnPointers[j + 1]); if (k < columnPointers[j + 1] && rowIndices[k] == i) { // if (Math.abs(value) < Matrices.EPS && value >= 0.0) { if (value == 0.0) { remove(k, j); } else { values[k] = value; } } else { insert(k, i, j, value); } } @Override public void setAll(double value) { if (value == 0.0) { cardinality = 0; } else { int size = (int) capacity(); if (values.length < size) { values = new double[size]; rowIndices = new int[size]; columnPointers = new int[columns + 1]; } for (int j = 0; j < columns; j++) { for (int i = 0; i < rows; i++) { values[j * rows + i] = value; rowIndices[j * rows + i] = i; } columnPointers[j] = rows * j; } columnPointers[columns] = size; cardinality = size; } } @Override public Vector getColumn(int j) { int columnCardinality = columnPointers[j + 1] - columnPointers[j]; double columnValues[] = new double[columnCardinality]; int columnIndices[] = new int[columnCardinality]; System.arraycopy(values, columnPointers[j], columnValues, 0, columnCardinality); System.arraycopy(rowIndices, columnPointers[j], columnIndices, 0, columnCardinality); return new CompressedVector(rows, columnCardinality, columnValues, columnIndices); } @Override public Vector getRow(int i) { Vector result = CompressedVector.zero(columns); int j = 0; while (columnPointers[j] < cardinality) { int k = searchForRowIndex(i, columnPointers[j], columnPointers[j + 1]); if (k < columnPointers[j + 1] && rowIndices[k] == i) { result.set(j, values[k]); } j++; } return result; } @Override public Matrix copyOfShape(int rows, int columns) { ensureDimensionsAreCorrect(rows, columns); if (rows >= this.rows && columns >= this.columns) { double $values[] = new double[align(cardinality)]; int $rowIndices[] = new int[align(cardinality)]; int $columnPointers[] = new int[columns + 1]; System.arraycopy(values, 0, $values, 0, cardinality); System.arraycopy(rowIndices, 0, $rowIndices, 0, cardinality); System.arraycopy(columnPointers, 0, $columnPointers, 0, this.columns + 1); for (int i = this.columns; i < columns + 1; i++) { $columnPointers[i] = cardinality; } return new CCSMatrix(rows, columns, cardinality, $values, $rowIndices, $columnPointers); } double $values[] = new double[align(cardinality)]; int $rowIndices[] = new int[align(cardinality)]; int $columnPointers[] = new int[columns + 1]; int $cardinality = 0; int k = 0, j = 0; while (k < cardinality && j < columns) { $columnPointers[j] = $cardinality; for (int i = columnPointers[j]; i < columnPointers[j + 1] && rowIndices[i] < rows; i++, k++) { $values[$cardinality] = values[i]; $rowIndices[$cardinality] = rowIndices[i]; $cardinality++; } j++; } for (; j < columns + 1; j++) { $columnPointers[j] = $cardinality; } return new CCSMatrix(rows, columns, $cardinality, $values, $rowIndices, $columnPointers); } @Override public void eachNonZero(MatrixProcedure procedure) { int k = 0, j = 0; while (k < cardinality) { for (int i = columnPointers[j]; i < columnPointers[j + 1]; i++, k++) { procedure.apply(rowIndices[i], j, values[i]); } j++; } } @Override public void each(MatrixProcedure procedure) { int k = 0; for (int i = 0; i < rows; i++) { int valuesSoFar = columnPointers[i + 1]; for (int j = 0; j < columns; j++) { if (k < valuesSoFar && j == rowIndices[k]) { procedure.apply(i, j, values[k++]); } else { procedure.apply(i, j, 0.0); } } } } @Override public void eachInColumn(int j, VectorProcedure procedure) { int k = columnPointers[j]; int valuesSoFar = columnPointers[j + 1]; for (int i = 0; i < rows; i++) { if (k < valuesSoFar && i == rowIndices[k]) { procedure.apply(i, values[k++]); } else { procedure.apply(i, 0.0); } } } @Override public void eachNonZeroInColumn(int j, VectorProcedure procedure) { for (int i = columnPointers[j]; i < columnPointers[j + 1]; i++) { procedure.apply(rowIndices[i], values[i]); } } @Override public void updateAt(int i, int j, MatrixFunction function) { int k = searchForRowIndex(i, columnPointers[j], columnPointers[j + 1]); if (k < columnPointers[j + 1] && rowIndices[k] == i) { double value = function.evaluate(i, j, values[k]); // if (Math.abs(value) < Matrices.EPS && value >= 0.0) { if (value == 0.0) { remove(k, j); } else { values[k] = value; } } else { insert(k, i, j, function.evaluate(i, j, 0.0)); } } @Override public boolean nonZeroAt(int i, int j) { int k = searchForRowIndex(i, columnPointers[j], columnPointers[j + 1]); return k < columnPointers[j + 1] && rowIndices[k] == i; } private int searchForRowIndex(int i, int left, int right) { if (right - left == 0 || i > rowIndices[right - 1]) { return right; } while (left < right) { int p = (left + right) / 2; if (rowIndices[p] > i) { right = p; } else if (rowIndices[p] < i) { left = p + 1; } else { return p; } } return left; } private void insert(int k, int i, int j, double value) { // if (Math.abs(value) < Matrices.EPS && value >= 0.0) { if (value == 0.0) { return; } if (values.length < cardinality + 1) { growUp(); } if (cardinality - k > 0) { System.arraycopy(values, k, values, k + 1, cardinality - k); System.arraycopy(rowIndices, k, rowIndices, k + 1, cardinality - k); } // for (int k = cardinality; k > position; k--) { // values[k] = values[k - 1]; // rowIndices[k] = rowIndices[k - 1]; // } values[k] = value; rowIndices[k] = i; for (int jj = j + 1; jj < columns + 1; jj++) { columnPointers[jj]++; } cardinality++; } private void remove(int k, int j) { cardinality--; if (cardinality - k > 0) { System.arraycopy(values, k + 1, values, k, cardinality - k); System.arraycopy(rowIndices, k + 1, rowIndices, k, cardinality - k); } // for (int kk = k; kk < cardinality; kk++) { // values[kk] = values[kk + 1]; // rowIndices[kk] = rowIndices[kk + 1]; // } for (int jj = j + 1; jj < columns + 1; jj++) { columnPointers[jj]--; } } private void growUp() { if (values.length == capacity()) { // This should never happen throw new IllegalStateException("This matrix can't grow up."); } int min = ( (rows != 0 && columns > Integer.MAX_VALUE / rows) ? Integer.MAX_VALUE : (rows * columns) ); int capacity = Math.min(min, (cardinality * 3) / 2 + 1); double $values[] = new double[capacity]; int $rowIndices[] = new int[capacity]; System.arraycopy(values, 0, $values, 0, cardinality); System.arraycopy(rowIndices, 0, $rowIndices, 0, cardinality); values = $values; rowIndices = $rowIndices; } private int align(int cardinality) { return ((cardinality / MINIMUM_SIZE) + 1) * MINIMUM_SIZE; } @Override public double max() { double max = Double.NEGATIVE_INFINITY; for (int i = 0; i < cardinality; i++) { if (values[i] > max) { max = values[i]; } } return (max > 0.0) ? max : 0.0; } @Override public double min() { double min = Double.POSITIVE_INFINITY; for (int i = 0; i < cardinality; i++) { if (values[i] < min) { min = values[i]; } } return (min < 0.0) ? min : 0.0; } @Override public double maxInColumn(int j) { double max = Double.NEGATIVE_INFINITY; for (int k = columnPointers[j]; k < columnPointers[j + 1]; k++) { if (values[k] > max) { max = values[k]; } } return (max > 0.0) ? max : 0.0; } @Override public double minInColumn(int j) { double min = Double.POSITIVE_INFINITY; for (int k = columnPointers[j]; k < columnPointers[j + 1]; k++) { if (values[k] < min) { min = values[k]; } } return (min < 0.0) ? min : 0.0; } /** * Returns a CCSMatrix with the selected rows and columns. */ @Override public Matrix select(int[] rowIndices, int[] columnIndices) { int newRows = rowIndices.length; int newCols = columnIndices.length; if (newRows == 0 || newCols == 0) { fail("No rows or columns selected."); } // determine number of non-zero values (cardinality) // before allocating space, this is perhaps more efficient // than single pass and calling grow() when required. int newCardinality = 0; for (int i = 0; i < newRows; i++) { for (int j = 0; j < newCols; j++) { if (get(rowIndices[i], columnIndices[j]) != 0.0) { newCardinality++; } } } // Construct the raw structure for the sparse matrix double[] newValues = new double[newCardinality]; int[] newRowIndices = new int[newCardinality]; int[] newColumnPointers = new int[newCols + 1]; newColumnPointers[0] = 0; int endPtr = 0; for (int j = 0; j < newCols; j++) { newColumnPointers[j + 1] = newColumnPointers[j]; for (int i = 0; i < newRows; i++) { double val = get(rowIndices[i], columnIndices[j]); if (val != 0.0) { newValues[endPtr] = val; newRowIndices[endPtr] = i; endPtr++; newColumnPointers[j + 1]++; } } } return new CCSMatrix(newRows, newCols, newCardinality, newValues, newRowIndices, newColumnPointers); } @Override public T to(MatrixFactory factory) { if (factory.outputClass == CCSMatrix.class) { return factory.outputClass.cast(this); } return super.to(factory); } @Override public Matrix blankOfShape(int rows, int columns) { return CCSMatrix.zero(rows, columns); } @Override public Iterator iteratorOrNonZeroColumns() { return new Iterator() { private int j = -1; @Override public boolean hasNext() { while (j + 1 < columns && columnPointers[j + 1] < cardinality && columnPointers[j + 1] == columnPointers[j + 2]) { j++; } return j + 1 < columns && columnPointers[j + 1] < cardinality; } @Override public Integer next() { j++; return j; } @Override public void remove() { throw new UnsupportedOperationException("Can not remove from this iterator."); } }; } @Override public ColumnMajorMatrixIterator columnMajorIterator() { return new ColumnMajorMatrixIterator(rows, columns) { private long limit = (long) rows * columns; private boolean currentNonZero = false; private int i = -1; private int k = 0; @Override public int rowIndex() { return i - columnIndex() * rows; } @Override public int columnIndex() { return i / rows; } @Override public double get() { return currentNonZero ? values[k] : 0.0; } @Override public void set(double value) { if (currentNonZero) { if (value == 0.0) { CCSMatrix.this.remove(k, columnIndex()); currentNonZero = false; } else { values[k] = value; } } else { CCSMatrix.this.insert(k, rowIndex(), columnIndex(), value); currentNonZero = true; } } @Override public boolean hasNext() { return i + 1 < limit; } @Override public Double next() { if (currentNonZero) { k++; } i++; currentNonZero = k < columnPointers[columnIndex() + 1] && rowIndices[k] == rowIndex(); return get(); } }; } @Override public ColumnMajorMatrixIterator nonZeroColumnMajorIterator() { return new ColumnMajorMatrixIterator(rows, columns) { private int j = 0; private int k = -1; private boolean currentIsRemoved = false; private int removedIndex = -1; @Override public int rowIndex() { return currentIsRemoved ? removedIndex : rowIndices[k]; } @Override public int columnIndex() { return j; } @Override public double get() { return currentIsRemoved ? 0.0 : values[k]; } @Override public void set(double value) { if (value == 0.0 && !currentIsRemoved) { currentIsRemoved = true; removedIndex = rowIndices[k]; CCSMatrix.this.remove(k--, j); } else if (value != 0.0 && !currentIsRemoved) { values[k] = value; } else { currentIsRemoved = false; CCSMatrix.this.insert(++k, removedIndex, j, value); } } @Override public boolean hasNext() { return k + 1 < cardinality; } @Override public Double next() { currentIsRemoved = false; k++; while (columnPointers[j + 1] == k) { j++; } return get(); } }; } @Override public VectorIterator nonZeroIteratorOfColumn(int j) { final int jj = j; return new VectorIterator(rows) { private int k = columnPointers[jj] - 1; private boolean currentIsRemoved = false; private int removedIndex = -1; @Override public int index() { return currentIsRemoved ? removedIndex : rowIndices[k]; } @Override public double get() { return currentIsRemoved ? 0.0 : values[k]; } @Override public void set(double value) { if (value == 0.0 && !currentIsRemoved) { currentIsRemoved = true; removedIndex = rowIndices[k]; CCSMatrix.this.remove(k--, jj); } else if (value != 0.0 && !currentIsRemoved) { values[k] = value; } else { currentIsRemoved = false; CCSMatrix.this.insert(++k, removedIndex, jj, value); } } @Override public boolean hasNext() { return k + 1 < columnPointers[jj + 1]; } @Override public Double next() { currentIsRemoved = false; return values[++k]; } }; } @Override public VectorIterator iteratorOfColumn(int j) { final int jj = j; return new VectorIterator(rows) { private int i = -1; private int k = columnPointers[jj]; @Override public int index() { return i; } @Override public double get() { if (k < columnPointers[jj + 1] && rowIndices[k] == i) { return values[k]; } return 0.0; } @Override public void set(double value) { if (k < columnPointers[jj + 1] && rowIndices[k] == i) { if (value == 0.0) { CCSMatrix.this.remove(k, jj); } else { values[k] = value; } } else { CCSMatrix.this.insert(k, i, jj, value); } } @Override public boolean hasNext() { return i + 1 < rows; } @Override public Double next() { i++; if (k < columnPointers[jj + 1] && rowIndices[k] == i - 1) { k++; } return get(); } }; } @Override public byte[] toBinary() { int size = 1 + // 1 byte: class tag 4 + // 4 bytes: rows 4 + // 4 bytes: columns 4 + // 4 bytes: cardinality (8 * cardinality) + // 8 * cardinality bytes: values (4 * cardinality) + // 4 * cardinality bytes: rowPointers (4 * (columns + 1)); // 4 * (columns + 1) bytes: columnIndices ByteBuffer buffer = ByteBuffer.allocate(size); buffer.put(MATRIX_TAG); buffer.putInt(rows); buffer.putInt(columns); buffer.putInt(cardinality); for (int i = 0; i < cardinality; i++) { buffer.putInt(rowIndices[i]); buffer.putDouble(values[i]); } for (int i = 0; i < columns + 1; i++) { buffer.putInt(columnPointers[i]); } return buffer.array(); } } la4j-0.6.0/src/main/java/org/la4j/matrix/sparse/CRSMatrix.java000066400000000000000000000746571263320764000237320ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Chandler May * Maxim Samoylov * Anveshi Charuvaka * Clement Skau * Catherine da Graca * */ package org.la4j.matrix.sparse; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.Random; import org.la4j.iterator.RowMajorMatrixIterator; import org.la4j.iterator.VectorIterator; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.MatrixFactory; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.matrix.functor.MatrixFunction; import org.la4j.matrix.functor.MatrixProcedure; import org.la4j.Vector; import org.la4j.vector.functor.VectorProcedure; import org.la4j.vector.sparse.CompressedVector; /** * This is a CRS (Compressed Row Storage) matrix class. */ public class CRSMatrix extends RowMajorSparseMatrix { private static final byte MATRIX_TAG = (byte) 0x20; /** * Creates a zero {@link CRSMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static CRSMatrix zero(int rows, int columns) { return new CRSMatrix(rows, columns); } /** * Creates a zero {@link CRSMatrix} of the given shape: * {@code rows} x {@code columns} with the given {@code capacity}. */ public static CRSMatrix zero(int rows, int columns, int capacity) { return new CRSMatrix(rows, columns, capacity); } /** * Creates a diagonal {@link CRSMatrix} of the given {@code size} whose * diagonal elements are equal to {@code diagonal}. */ public static CRSMatrix diagonal(int size, double diagonal) { double values[] = new double[size]; int columnIndices[] = new int[size]; int rowPointers[] = new int[size + 1]; for (int i = 0; i < size; i++) { columnIndices[i] = i; rowPointers[i] = i; values[i] = diagonal; } rowPointers[size] = size; return new CRSMatrix(size, size, size, values, columnIndices, rowPointers); } /** * Creates an identity {@link CRSMatrix} of the given {@code size}. */ public static CRSMatrix identity(int size) { return CRSMatrix.diagonal(size, 1.0); } /** * Creates a random {@link CRSMatrix} of the given shape: * {@code rows} x {@code columns}. */ public static CRSMatrix random(int rows, int columns, double density, Random random) { if (density < 0.0 || density > 1.0) { throw new IllegalArgumentException("The density value should be between 0 and 1.0"); } int cardinality = Math.max((int) ((rows * columns) * density), rows); double values[] = new double[cardinality]; int columnIndices[] = new int[cardinality]; int rowPointers[] = new int[rows + 1]; int kk = cardinality / rows; int indices[] = new int[kk]; int k = 0; for (int i = 0; i < rows; i++) { rowPointers[i] = k; for (int ii = 0; ii < kk; ii++) { indices[ii] = random.nextInt(columns); } Arrays.sort(indices); int previous = -1; for (int ii = 0; ii < kk; ii++) { if (indices[ii] == previous) { continue; } values[k] = random.nextDouble(); columnIndices[k++] = indices[ii]; previous = indices[ii]; } } rowPointers[rows] = cardinality; return new CRSMatrix(rows, columns, cardinality, values, columnIndices, rowPointers); } /** * Creates a random symmetric {@link CRSMatrix} of the given {@code size}. */ public static CRSMatrix randomSymmetric(int size, double density, Random random) { int cardinality = (int) ((size * size) * density); // TODO: Issue 15 // We can do better here. All we need to is to make sure // that all the writes to CRS matrix are done in a serial // order (row-major). This will give us O(1) performance // per write. CRSMatrix matrix = new CRSMatrix(size, size, cardinality); for (int k = 0; k < cardinality / 2; k++) { int i = random.nextInt(size); int j = random.nextInt(size); double value = random.nextDouble(); matrix.set(i, j, value); matrix.set(j, i, value); } return matrix; } /** * Creates a new {@link CRSMatrix} from the given 1D {@code array} with * compressing (copying) the underlying array. */ public static CRSMatrix from1DArray(int rows, int columns, double[] array) { CRSMatrix result = CRSMatrix.zero(rows, columns); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { int k = i * columns + j; if (array[k] != 0.0) { result.set(i, j, array[k]); } } } return result; } /** * Creates a new {@link CRSMatrix} from the given 2D {@code array} with * compressing (copying) the underlying array. */ public static CRSMatrix from2DArray(double[][] array) { int rows = array.length; int columns = array[0].length; CRSMatrix result = CRSMatrix.zero(rows, columns); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if (array[i][j] != 0.0) { result.set(i, j, array[i][j]); } } } return result; } /** * Creates a block {@link CRSMatrix} of the given blocks {@code a}, * {@code b}, {@code c} and {@code d}. */ public static CRSMatrix block(Matrix a, Matrix b, Matrix c, Matrix d) { if ((a.rows() != b.rows()) || (a.columns() != c.columns()) || (c.rows() != d.rows()) || (b.columns() != d.columns())) { throw new IllegalArgumentException("Sides of blocks are incompatible!"); } int rows = a.rows() + c.rows(), columns = a.columns() + b.columns(); ArrayList values = new ArrayList(); ArrayList columnIndices = new ArrayList(); int rowPointers[] = new int[rows + 1]; int k = 0; rowPointers[0] = 0; double current = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if ((i < a.rows()) && (j < a.columns())) { current = a.get(i, j); } if ((i < a.rows()) && (j > a.columns())) { current = b.get(i, j); } if ((i > a.rows()) && (j < a.columns())) { current = c.get(i, j); } if ((i > a.rows()) && (j > a.columns())) { current = d.get(i, j); } if (Math.abs(current) > Matrices.EPS) { values.add(current); columnIndices.add(j); k++; } } rowPointers[i + 1] = k; } double valuesArray[] = new double[values.size()]; int colIndArray[] = new int[columnIndices.size()]; for (int i = 0; i < values.size(); i++) { valuesArray[i] = values.get(i); colIndArray[i] = columnIndices.get(i); } return new CRSMatrix(rows, columns, k, valuesArray, colIndArray, rowPointers); } /** * Decodes {@link CRSMatrix} from the given byte {@code array}. * * @param array the byte array representing a matrix * * @return a decoded matrix */ public static CRSMatrix fromBinary(byte[] array) { ByteBuffer buffer = ByteBuffer.wrap(array); if (buffer.get() != MATRIX_TAG) { throw new IllegalArgumentException("Can not decode CRSMatrix from the given byte array."); } int rows = buffer.getInt(); int columns = buffer.getInt(); int cardinality = buffer.getInt(); int[] columnIndices = new int[cardinality]; double[] values = new double[cardinality]; int[] rowPointers = new int[rows + 1]; for (int i = 0; i < cardinality; i++) { columnIndices[i] = buffer.getInt(); values[i] = buffer.getDouble(); } for (int i = 0; i < rows + 1; i++) { rowPointers[i] = buffer.getInt(); } return new CRSMatrix(rows, columns, cardinality, values, columnIndices, rowPointers); } /** * Parses {@link CRSMatrix} from the given CSV string. * * @param csv the CSV string representing a matrix * * @return a parsed matrix */ public static CRSMatrix fromCSV(String csv) { return Matrix.fromCSV(csv).to(Matrices.CRS); } /** * Parses {@link CRSMatrix} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed matrix */ public static CRSMatrix fromMatrixMarket(String mm) { return Matrix.fromMatrixMarket(mm).to(Matrices.CRS); } private static final int MINIMUM_SIZE = 32; private double values[]; private int columnIndices[]; private int rowPointers[]; public CRSMatrix() { this(0, 0); } public CRSMatrix(int rows, int columns) { this(rows, columns, 0); } public CRSMatrix(int rows, int columns, int capacity) { super(rows, columns); ensureCardinalityIsCorrect(rows, columns, capacity); int alignedSize = align(capacity); this.values = new double[alignedSize]; this.columnIndices = new int[alignedSize]; this.rowPointers = new int[rows + 1]; } public CRSMatrix(int rows, int columns, int cardinality, double values[], int columnIndices[], int rowPointers[]) { super(rows, columns, cardinality); ensureCardinalityIsCorrect(rows, columns, cardinality); this.values = values; this.columnIndices = columnIndices; this.rowPointers = rowPointers; } @Override public double getOrElse(int i, int j, double defaultValue) { ensureIndexesAreInBounds(i, j); int k = searchForColumnIndex(j, rowPointers[i], rowPointers[i + 1]); if (k < rowPointers[i + 1] && columnIndices[k] == j) { return values[k]; } return defaultValue; } @Override public void set(int i, int j, double value) { ensureIndexesAreInBounds(i, j); int k = searchForColumnIndex(j, rowPointers[i], rowPointers[i + 1]); if (k < rowPointers[i + 1] && columnIndices[k] == j) { // if (Math.abs(value) < Matrices.EPS && value >= 0.0) { if (value == 0.0) { remove(k, i); } else { values[k] = value; } } else { insert(k, i, j, value); } } @Override public void setAll(double value) { if (value == 0.0) { cardinality = 0; } else { int size = (int) capacity(); if (values.length < size) { values = new double[size]; columnIndices = new int[size]; rowPointers = new int[rows + 1]; } for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { values[i * columns + j] = value; columnIndices[i * columns + j] = j; } rowPointers[i] = columns * i; } rowPointers[rows] = size; cardinality = size; } } @Override public Vector getRow(int i) { int rowCardinality = rowPointers[i + 1] - rowPointers[i]; double rowValues[] = new double[rowCardinality]; int rowIndices[] = new int[rowCardinality]; System.arraycopy(values, rowPointers[i], rowValues, 0, rowCardinality); System.arraycopy(columnIndices, rowPointers[i], rowIndices, 0, rowCardinality); return new CompressedVector(columns, rowCardinality, rowValues, rowIndices); } @Override public Vector getColumn(int j) { Vector result = CompressedVector.zero(rows); int i = 0; while (rowPointers[i] < cardinality) { int k = searchForColumnIndex(j, rowPointers[i], rowPointers[i + 1]); if (k < rowPointers[i + 1] && columnIndices[k] == j) { result.set(i, values[k]); } i++; } return result; } @Override public Matrix copyOfShape(int rows, int columns) { ensureDimensionsAreCorrect(rows, columns); if (rows >= this.rows && columns >= this.columns) { double $values[] = new double[align(cardinality)]; int $columnIndices[] = new int[align(cardinality)]; int $rowPointers[] = new int[rows + 1]; System.arraycopy(values, 0, $values, 0, cardinality); System.arraycopy(columnIndices, 0, $columnIndices, 0, cardinality); System.arraycopy(rowPointers, 0, $rowPointers, 0, this.rows + 1); for (int i = this.rows; i < rows + 1; i++) { $rowPointers[i] = cardinality; } return new CRSMatrix(rows, columns, cardinality, $values, $columnIndices, $rowPointers); } double $values[] = new double[align(cardinality)]; int $columnIndices[] = new int[align(cardinality)]; int $rowPointers[] = new int[rows + 1]; int $cardinality = 0; int k = 0, i = 0; while (k < cardinality && i < rows) { $rowPointers[i] = $cardinality; for (int j = rowPointers[i]; j < rowPointers[i + 1] && columnIndices[j] < columns; j++, k++) { $values[$cardinality] = values[j]; $columnIndices[$cardinality] = columnIndices[j]; $cardinality++; } i++; } for (; i < rows + 1; i++) { $rowPointers[i] = $cardinality; } return new CRSMatrix(rows, columns, $cardinality, $values, $columnIndices, $rowPointers); } @Override public void eachNonZero(MatrixProcedure procedure) { int k = 0, i = 0; while (k < cardinality) { for (int j = rowPointers[i]; j < rowPointers[i + 1]; j++, k++) { procedure.apply(i, columnIndices[j], values[j]); } i++; } } @Override public void each(MatrixProcedure procedure) { int k = 0; for (int i = 0; i < rows; i++) { int valuesSoFar = rowPointers[i + 1]; for (int j = 0; j < columns; j++) { if (k < valuesSoFar && j == columnIndices[k]) { procedure.apply(i, j, values[k++]); } else { procedure.apply(i, j, 0.0); } } } } @Override public void eachInRow(int i, VectorProcedure procedure) { int k = rowPointers[i]; int valuesSoFar = rowPointers[i + 1]; for (int j = 0; j < columns; j++) { if (k < valuesSoFar && j == columnIndices[k]) { procedure.apply(j, values[k++]); } else { procedure.apply(j, 0.0); } } } @Override public void eachNonZeroInRow(int i, VectorProcedure procedure) { for (int j = rowPointers[i]; j < rowPointers[i + 1]; j++) { procedure.apply(columnIndices[j], values[j]); } } @Override public void updateAt(int i, int j, MatrixFunction function) { int k = searchForColumnIndex(j, rowPointers[i], rowPointers[i + 1]); if (k < rowPointers[i + 1] && columnIndices[k] == j) { double value = function.evaluate(i, j, values[k]); // if (Math.abs(value) < Matrices.EPS && value >= 0.0) { if (value == 0.0) { remove(k, i); } else { values[k] = value; } } else { insert(k, i, j, function.evaluate(i, j, 0)); } } @Override public boolean nonZeroAt(int i, int j) { int k = searchForColumnIndex(j, rowPointers[i], rowPointers[i + 1]); return k < rowPointers[i + 1] && columnIndices[k] == j; } private int searchForColumnIndex(int j, int left, int right) { if (right - left == 0 || j > columnIndices[right - 1]) { return right; } while (left < right) { int p = (left + right) / 2; if (columnIndices[p] > j) { right = p; } else if (columnIndices[p] < j) { left = p + 1; } else { return p; } } return left; } private void insert(int k, int i, int j, double value) { //if (Math.abs(value) < Matrices.EPS && value >= 0.0) { if (value == 0.0) { return; } if (values.length < cardinality + 1) { growUp(); } if (cardinality - k > 0) { System.arraycopy(values, k, values, k + 1, cardinality - k); System.arraycopy(columnIndices, k, columnIndices, k + 1, cardinality - k); } // for (int k = cardinality; k > position; k--) { // values[k] = values[k - 1]; // columnIndices[k] = columnIndices[k - 1]; // } values[k] = value; columnIndices[k] = j; for (int ii = i + 1; ii < rows + 1; ii++) { rowPointers[ii]++; } cardinality++; } private void remove(int k, int i) { cardinality--; if (cardinality - k > 0) { System.arraycopy(values, k + 1, values, k, cardinality - k); System.arraycopy(columnIndices, k + 1, columnIndices, k, cardinality - k); } // for (int kk = k; kk < cardinality; kk++) { // values[kk] = values[kk + 1]; // columnIndices[kk] = columnIndices[kk + 1]; // } for (int ii = i + 1; ii < rows + 1; ii++) { rowPointers[ii]--; } } private void growUp() { if (values.length == capacity()) { // This should never happen throw new IllegalStateException("This matrix can't grow up."); } int min = ( (rows != 0 && columns > Integer.MAX_VALUE / rows) ? Integer.MAX_VALUE : (rows * columns) ); int capacity = Math.min(min, (cardinality * 3) / 2 + 1); double $values[] = new double[capacity]; int $columnIndices[] = new int[capacity]; System.arraycopy(values, 0, $values, 0, cardinality); System.arraycopy(columnIndices, 0, $columnIndices, 0, cardinality); values = $values; columnIndices = $columnIndices; } private int align(int cardinality) { return ((cardinality / MINIMUM_SIZE) + 1) * MINIMUM_SIZE; } @Override public double max() { double max = Double.NEGATIVE_INFINITY; for (int i = 0; i < cardinality; i++) { if (values[i] > max) { max = values[i]; } } return (max > 0.0) ? max : 0.0; } @Override public double min() { double min = Double.POSITIVE_INFINITY; for (int i = 0; i < cardinality; i++) { if (values[i] < min) { min = values[i]; } } return (min < 0.0) ? min : 0.0; } @Override public double maxInRow(int i) { double max = Double.NEGATIVE_INFINITY; for (int k = rowPointers[i]; k < rowPointers[i + 1]; k++) { if (values[k] > max) { max = values[k]; } } return (max > 0.0) ? max : 0.0; } @Override public double minInRow(int i) { double min = Double.POSITIVE_INFINITY; for (int k = rowPointers[i]; k < rowPointers[i + 1]; k++) { if (values[k] < min) { min = values[k]; } } return (min < 0.0) ? min : 0.0; } /** * Returns a CRSMatrix with the selected rows and columns. */ @Override public Matrix select(int[] rowIndices, int[] columnIndices) { int newRows = rowIndices.length; int newCols = columnIndices.length; if (newRows == 0 || newCols == 0) { fail("No rows or columns selected."); } // determine number of non-zero values (cardinality) // before allocating space, this is perhaps more efficient // than single pass and calling grow() when required. int newCardinality = 0; for (int i = 0; i < newRows; i++) { for (int j = 0; j < newCols; j++) { if (get(rowIndices[i], columnIndices[j]) != 0.0) { newCardinality++; } } } // Construct the raw structure for the sparse matrix double[] newValues = new double[newCardinality]; int[] newColumnIndices = new int[newCardinality]; int[] newRowPointers = new int[newRows + 1]; newRowPointers[0] = 0; int endPtr = 0; for (int i = 0; i < newRows; i++) { newRowPointers[i + 1] = newRowPointers[i]; for (int j = 0; j < newCols; j++) { double val = get(rowIndices[i], columnIndices[j]); if (val != 0.0) { newValues[endPtr] = val; newColumnIndices[endPtr] = j; endPtr++; newRowPointers[i + 1] += 1; } } } return new CRSMatrix(newRows, newCols, newCardinality, newValues, newColumnIndices, newRowPointers); } @Override public T to(MatrixFactory factory) { if (factory.outputClass == CRSMatrix.class) { return factory.outputClass.cast(this); } return super.to(factory); } @Override public Matrix blankOfShape(int rows, int columns) { return CRSMatrix.zero(rows, columns); } @Override public Iterator iteratorOfNonZeroRows() { return new Iterator() { private int i = -1; @Override public boolean hasNext() { while (i + 1 < rows && rowPointers[i + 1] < cardinality && rowPointers[i + 1] == rowPointers[i + 2]) { i++; } return i + 1 < rows && rowPointers[i + 1] < cardinality ; } @Override public Integer next() { i++; return i; } @Override public void remove() { throw new UnsupportedOperationException("Can not remove from this iterator."); } }; } @Override public RowMajorMatrixIterator rowMajorIterator() { return new RowMajorMatrixIterator(rows, columns) { private long limit = (long) rows * columns; private boolean currentNonZero = false; private int i = -1; private int k = 0; @Override public int rowIndex() { return i / columns; } @Override public int columnIndex() { return i - rowIndex() * columns; } @Override public double get() { return currentNonZero ? values[k] : 0.0; } @Override public void set(double value) { if (currentNonZero) { if (value == 0.0) { CRSMatrix.this.remove(k, rowIndex()); currentNonZero = false; } else { values[k] = value; } } else { CRSMatrix.this.insert(k, rowIndex(), columnIndex(), value); currentNonZero = true; } } @Override public boolean hasNext() { return i + 1 < limit; } @Override public Double next() { if (currentNonZero) { k++; } i++; currentNonZero = k < rowPointers[rowIndex() + 1] && columnIndices[k] == columnIndex(); return get(); } }; } @Override public RowMajorMatrixIterator nonZeroRowMajorIterator() { return new RowMajorMatrixIterator(rows, columns) { private int i = 0; private int k = -1; private boolean currentIsRemoved = false; private int removedIndex = -1; @Override public int rowIndex() { return i; } @Override public int columnIndex() { return currentIsRemoved ? removedIndex : columnIndices[k]; } @Override public double get() { return currentIsRemoved ? 0.0 : values[k]; } @Override public void set(double value) { if (value == 0.0 && !currentIsRemoved) { currentIsRemoved = true; removedIndex = columnIndices[k]; CRSMatrix.this.remove(k--, i); } else if (value != 0.0 && !currentIsRemoved) { values[k] = value; } else { currentIsRemoved = false; CRSMatrix.this.insert(++k, i, removedIndex, value); } } @Override public boolean hasNext() { return k + 1 < cardinality; } @Override public Double next() { currentIsRemoved = false; k++; while (rowPointers[i + 1] == k) { i++; } return get(); } }; } @Override public VectorIterator nonZeroIteratorOfRow(int i) { final int ii = i; return new VectorIterator(columns) { private int k = rowPointers[ii] - 1; private boolean currentIsRemoved = false; private int removedIndex = -1; @Override public int index() { return currentIsRemoved ? removedIndex : columnIndices[k]; } @Override public double get() { return currentIsRemoved ? 0.0 : values[k]; } @Override public void set(double value) { if (value == 0.0 && !currentIsRemoved) { currentIsRemoved = true; removedIndex = columnIndices[k]; CRSMatrix.this.remove(k--, ii); } else if (value != 0.0 && !currentIsRemoved) { values[k] = value; } else { currentIsRemoved = false; CRSMatrix.this.insert(++k, ii, removedIndex, value); } } @Override public boolean hasNext() { return k + 1 < rowPointers[ii + 1]; } @Override public Double next() { currentIsRemoved = false; return values[++k]; } }; } @Override public VectorIterator iteratorOfRow(int i) { final int ii = i; return new VectorIterator(columns) { private int j = -1; private int k = rowPointers[ii]; @Override public int index() { return j; } @Override public double get() { if (k < rowPointers[ii + 1] && columnIndices[k] == j) { return values[k]; } return 0.0; } @Override public void set(double value) { if (k < rowPointers[ii + 1] && columnIndices[k] == j) { if (value == 0.0) { CRSMatrix.this.remove(k, ii); } else { values[k] = value; } } else { CRSMatrix.this.insert(k, ii, j, value); } } @Override public boolean hasNext() { return j + 1 < columns; } @Override public Double next() { j++; if (k < rowPointers[ii + 1] && columnIndices[k] == j - 1) { k++; } return get(); } }; } @Override public byte[] toBinary() { int size = 1 + // 1 byte: class tag 4 + // 4 bytes: rows 4 + // 4 bytes: columns 4 + // 4 bytes: cardinality (8 * cardinality) + // 8 * cardinality bytes: values (4 * cardinality) + // 4 * cardinality bytes: columnPointers (4 * (rows + 1)); // 4 * (rows + 1) bytes: rowIndices ByteBuffer buffer = ByteBuffer.allocate(size); buffer.put(MATRIX_TAG); buffer.putInt(rows); buffer.putInt(columns); buffer.putInt(cardinality); for (int i = 0; i < cardinality; i++) { buffer.putInt(columnIndices[i]); buffer.putDouble(values[i]); } for (int i = 0; i < rows + 1; i++) { buffer.putInt(rowPointers[i]); } return buffer.array(); } } la4j-0.6.0/src/main/java/org/la4j/operation/000077500000000000000000000000001263320764000204275ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/operation/CommonMatrixMatrixOperation.java000066400000000000000000000041301263320764000267530ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; public abstract class CommonMatrixMatrixOperation extends MatrixMatrixOperation { @Override public R apply(DenseMatrix a, DenseMatrix b) { return applyCommon(a, b); } @Override public R apply(DenseMatrix a, RowMajorSparseMatrix b) { return applyCommon(a, b); } @Override public R apply(DenseMatrix a, ColumnMajorSparseMatrix b) { return applyCommon(a, b); } @Override public R apply(RowMajorSparseMatrix a, DenseMatrix b) { return applyCommon(a, b); } @Override public R apply(RowMajorSparseMatrix a, RowMajorSparseMatrix b) { return applyCommon(a, b); } @Override public R apply(RowMajorSparseMatrix a, ColumnMajorSparseMatrix b) { return applyCommon(a, b); } @Override public R apply(ColumnMajorSparseMatrix a, DenseMatrix b) { return applyCommon(a, b); } @Override public R apply(ColumnMajorSparseMatrix a, RowMajorSparseMatrix b) { return applyCommon(a, b); } @Override public R apply(ColumnMajorSparseMatrix a, ColumnMajorSparseMatrix b) { return applyCommon(a, b); } public abstract R applyCommon(final Matrix a, final Matrix b); } la4j-0.6.0/src/main/java/org/la4j/operation/CommonMatrixOperation.java000066400000000000000000000024421263320764000255720ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; public abstract class CommonMatrixOperation extends MatrixOperation { @Override public R apply(DenseMatrix a) { return applyCommon(a); } @Override public R apply(RowMajorSparseMatrix a) { return applyCommon(a); } @Override public R apply(ColumnMajorSparseMatrix a) { return applyCommon(a); } public abstract R applyCommon(final Matrix a); } la4j-0.6.0/src/main/java/org/la4j/operation/CommonVectorOperation.java000066400000000000000000000022021263320764000255620ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Vector; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public abstract class CommonVectorOperation extends VectorOperation { @Override public R apply(final SparseVector a) { return applyCommon(a); } @Override public R apply(final DenseVector a) { return applyCommon(a); } abstract R applyCommon(final Vector a); } la4j-0.6.0/src/main/java/org/la4j/operation/CommonVectorVectorOperation.java000066400000000000000000000027041263320764000267540ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Vector; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public abstract class CommonVectorVectorOperation extends VectorVectorOperation { @Override public R apply(final SparseVector a, final SparseVector b) { return applyCommon(a, b); } @Override public R apply(final SparseVector a, final DenseVector b) { return applyCommon(a, b); } @Override public R apply(final DenseVector a, final DenseVector b) { return applyCommon(a, b); } @Override public R apply(final DenseVector a, final SparseVector b) { return applyCommon(a, b); } public abstract R applyCommon(final Vector a, final Vector b); } la4j-0.6.0/src/main/java/org/la4j/operation/MatrixMatrixOperation.java000066400000000000000000000077461263320764000256220ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; public abstract class MatrixMatrixOperation { public abstract R apply(final DenseMatrix a, final DenseMatrix b); public abstract R apply(final DenseMatrix a, final RowMajorSparseMatrix b); public abstract R apply(final DenseMatrix a, final ColumnMajorSparseMatrix b); public abstract R apply(final RowMajorSparseMatrix a, final DenseMatrix b); public abstract R apply(final RowMajorSparseMatrix a, final RowMajorSparseMatrix b); public abstract R apply(final RowMajorSparseMatrix a, final ColumnMajorSparseMatrix b); public abstract R apply(final ColumnMajorSparseMatrix a, final DenseMatrix b); public abstract R apply(final ColumnMajorSparseMatrix a, final RowMajorSparseMatrix b); public abstract R apply(final ColumnMajorSparseMatrix a, final ColumnMajorSparseMatrix b); public void ensureApplicableTo(final Matrix a, final Matrix b) { } public MatrixOperation partiallyApply(final DenseMatrix a) { return new MatrixOperation() { @Override public R apply(final DenseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public R apply(final RowMajorSparseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public R apply(final ColumnMajorSparseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Matrix b) { MatrixMatrixOperation.this.ensureApplicableTo(a, b); } }; } public MatrixOperation partiallyApply(final RowMajorSparseMatrix a) { return new MatrixOperation() { @Override public R apply(DenseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public R apply(RowMajorSparseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public R apply(ColumnMajorSparseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Matrix b) { MatrixMatrixOperation.this.ensureApplicableTo(a, b); } }; } public MatrixOperation partiallyApply(final ColumnMajorSparseMatrix a) { return new MatrixOperation() { @Override public R apply(DenseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public R apply(RowMajorSparseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public R apply(ColumnMajorSparseMatrix b) { return MatrixMatrixOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Matrix b) { MatrixMatrixOperation.this.ensureApplicableTo(a, b); } }; } } la4j-0.6.0/src/main/java/org/la4j/operation/MatrixOperation.java000066400000000000000000000022231263320764000244160ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; public abstract class MatrixOperation { public abstract R apply(final DenseMatrix a); public abstract R apply(final RowMajorSparseMatrix a); public abstract R apply(final ColumnMajorSparseMatrix a); public void ensureApplicableTo(final Matrix a) { } } la4j-0.6.0/src/main/java/org/la4j/operation/MatrixVectorOperation.java000066400000000000000000000065061263320764000256110ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.Vector; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public abstract class MatrixVectorOperation { public abstract R apply(final DenseMatrix a, final DenseVector b); public abstract R apply(final DenseMatrix a, final SparseVector b); public abstract R apply(final RowMajorSparseMatrix a, final DenseVector b); public abstract R apply(final RowMajorSparseMatrix a, final SparseVector b); public abstract R apply(final ColumnMajorSparseMatrix a, final DenseVector b); public abstract R apply(final ColumnMajorSparseMatrix a, final SparseVector b); public void ensureApplicableTo(final Matrix a, final Vector b) { } public VectorOperation partiallyApply(final DenseMatrix a) { return new VectorOperation() { @Override public R apply(final SparseVector b) { return MatrixVectorOperation.this.apply(a, b); } @Override public R apply(final DenseVector b) { return MatrixVectorOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Vector b) { MatrixVectorOperation.this.ensureApplicableTo(a, b); } }; } public VectorOperation partiallyApply(final RowMajorSparseMatrix a) { return new VectorOperation() { @Override public R apply(final SparseVector b) { return MatrixVectorOperation.this.apply(a, b); } @Override public R apply(final DenseVector b) { return MatrixVectorOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Vector b) { MatrixVectorOperation.this.ensureApplicableTo(a, b); } }; } public VectorOperation partiallyApply(final ColumnMajorSparseMatrix a) { return new VectorOperation() { @Override public R apply(final SparseVector b) { return MatrixVectorOperation.this.apply(a, b); } @Override public R apply(final DenseVector b) { return MatrixVectorOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Vector b) { MatrixVectorOperation.this.ensureApplicableTo(a, b); } }; } } la4j-0.6.0/src/main/java/org/la4j/operation/SimpleMatrixMatrixOperation.java000066400000000000000000000036461263320764000267670ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.matrix.SparseMatrix; public abstract class SimpleMatrixMatrixOperation extends MatrixMatrixOperation { @Override public R apply(DenseMatrix a, RowMajorSparseMatrix b) { return applySimple(a, b); } @Override public R apply(DenseMatrix a, ColumnMajorSparseMatrix b) { return applySimple(a, b); } @Override public R apply(RowMajorSparseMatrix a, DenseMatrix b) { return applySimple(a, b); } @Override public R apply(ColumnMajorSparseMatrix a, DenseMatrix b) { return applySimple(a, b); } @Override public R apply(RowMajorSparseMatrix a, RowMajorSparseMatrix b) { return applySimple(a, b); } @Override public R apply(ColumnMajorSparseMatrix a, ColumnMajorSparseMatrix b) { return applySimple(a, b); } public abstract R applySimple(final DenseMatrix a, final SparseMatrix b); public abstract R applySimple(final SparseMatrix a, final DenseMatrix b); public abstract R applySimple(final SparseMatrix a, final SparseMatrix b); } la4j-0.6.0/src/main/java/org/la4j/operation/SymmetricMatrixMatrixOperation.java000066400000000000000000000030201263320764000274740ustar00rootroot00000000000000package org.la4j.operation; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.matrix.SparseMatrix; public abstract class SymmetricMatrixMatrixOperation extends MatrixMatrixOperation { @Override public R apply(DenseMatrix a, RowMajorSparseMatrix b) { return applySymmetric(a, b); } @Override public R apply(DenseMatrix a, ColumnMajorSparseMatrix b) { return applySymmetric(a, b); } @Override public R apply(RowMajorSparseMatrix a, DenseMatrix b) { return applySymmetric(b, a); } @Override public R apply(RowMajorSparseMatrix a, ColumnMajorSparseMatrix b) { return applySymmetric(a, b); } @Override public R apply(ColumnMajorSparseMatrix a, DenseMatrix b) { return applySymmetric(b, a); } @Override public R apply(RowMajorSparseMatrix a, RowMajorSparseMatrix b) { return applySymmetric(a, b); } @Override public R apply(ColumnMajorSparseMatrix a, ColumnMajorSparseMatrix b) { return applySymmetric(a, b); } @Override public R apply(ColumnMajorSparseMatrix a, RowMajorSparseMatrix b) { return applySymmetric(b, a); } public abstract R applySymmetric(final DenseMatrix a, final SparseMatrix b); public abstract R applySymmetric(final SparseMatrix a, final SparseMatrix b); public abstract R applySymmetric(final RowMajorSparseMatrix a, final ColumnMajorSparseMatrix b); } la4j-0.6.0/src/main/java/org/la4j/operation/SymmetricVectorVectorOperation.java000066400000000000000000000022761263320764000275040ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public abstract class SymmetricVectorVectorOperation extends VectorVectorOperation { @Override public R apply(SparseVector a, DenseVector b) { return applySymmetric(b, a); } @Override public R apply(DenseVector a, SparseVector b) { return applySymmetric(a, b); } public abstract R applySymmetric(final DenseVector a, final SparseVector b); } la4j-0.6.0/src/main/java/org/la4j/operation/VectorMatrixOperation.java000066400000000000000000000060631263320764000256070ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.Vector; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public abstract class VectorMatrixOperation { public abstract R apply(final SparseVector a, final DenseMatrix b); public abstract R apply(final SparseVector a, final RowMajorSparseMatrix b); public abstract R apply(final SparseVector a, final ColumnMajorSparseMatrix b); public abstract R apply(final DenseVector a, final DenseMatrix b); public abstract R apply(final DenseVector a, final RowMajorSparseMatrix b); public abstract R apply(final DenseVector a, final ColumnMajorSparseMatrix b); public void ensureApplicableTo(final Vector a, final Matrix b) { } public MatrixOperation partiallyApply(final SparseVector a) { return new MatrixOperation() { @Override public R apply(final DenseMatrix b) { return VectorMatrixOperation.this.apply(a, b); } @Override public R apply(final RowMajorSparseMatrix b) { return VectorMatrixOperation.this.apply(a, b); } @Override public R apply(final ColumnMajorSparseMatrix b) { return VectorMatrixOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Matrix b) { VectorMatrixOperation.this.ensureApplicableTo(a, b); } }; } public MatrixOperation partiallyApply(final DenseVector a) { return new MatrixOperation() { @Override public R apply(final DenseMatrix b) { return VectorMatrixOperation.this.apply(a, b); } @Override public R apply(final RowMajorSparseMatrix b) { return VectorMatrixOperation.this.apply(a, b); } @Override public R apply(final ColumnMajorSparseMatrix b) { return VectorMatrixOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Matrix b) { VectorMatrixOperation.this.ensureApplicableTo(a, b); } }; } } la4j-0.6.0/src/main/java/org/la4j/operation/VectorOperation.java000066400000000000000000000020251263320764000244140ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Vector; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public abstract class VectorOperation { public abstract R apply(final SparseVector a); public abstract R apply(final DenseVector a); public void ensureApplicableTo(final Vector a) { } } la4j-0.6.0/src/main/java/org/la4j/operation/VectorVectorOperation.java000066400000000000000000000046161263320764000256070ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation; import org.la4j.Vector; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public abstract class VectorVectorOperation { public abstract R apply(final SparseVector a, final SparseVector b); public abstract R apply(final SparseVector a, final DenseVector b); public abstract R apply(final DenseVector a, final DenseVector b); public abstract R apply(final DenseVector a, final SparseVector b); public void ensureApplicableTo(final Vector a, final Vector b) { } public VectorOperation partiallyApply(final SparseVector a) { return new VectorOperation() { @Override public R apply(final SparseVector b) { return VectorVectorOperation.this.apply(a, b); } @Override public R apply(final DenseVector b) { return VectorVectorOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Vector b) { VectorVectorOperation.this.ensureApplicableTo(a, b); } }; } public VectorOperation partiallyApply(final DenseVector a) { return new VectorOperation() { @Override public R apply(final SparseVector b) { return VectorVectorOperation.this.apply(a, b); } @Override public R apply(final DenseVector b) { return VectorVectorOperation.this.apply(a, b); } @Override public void ensureApplicableTo(final Vector b) { VectorVectorOperation.this.ensureApplicableTo(a, b); } }; } } la4j-0.6.0/src/main/java/org/la4j/operation/inplace/000077500000000000000000000000001263320764000220425ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/operation/inplace/InPlaceCopyMatrixToMatrix.java000066400000000000000000000050731263320764000277350ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.inplace; import org.la4j.iterator.MatrixIterator; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.operation.SimpleMatrixMatrixOperation; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.matrix.SparseMatrix; public class InPlaceCopyMatrixToMatrix extends SimpleMatrixMatrixOperation { @Override public Matrix applySimple(DenseMatrix a, SparseMatrix b) { MatrixIterator it = b.iterator(); while (it.hasNext()) { it.next(); int i = it.rowIndex(); int j = it.columnIndex(); double x = a.get(i, j); if (x != 0.0) { it.set(x); } } return b; } @Override public Matrix applySimple(SparseMatrix a, DenseMatrix b) { return fromSparseToMatrix(a, b); } @Override public Matrix applySimple(SparseMatrix a, SparseMatrix b) { return fromSparseToMatrix(a, b); } @Override public Matrix apply(DenseMatrix a, DenseMatrix b) { for (int i = 0; i < a.rows(); i++) { for (int j = 0; j < a.columns(); j++) { b.set(i, j, a.get(i, j)); } } return b; } @Override public Matrix apply(RowMajorSparseMatrix a, ColumnMajorSparseMatrix b) { return fromSparseToMatrix(a, b); } @Override public Matrix apply(ColumnMajorSparseMatrix a, RowMajorSparseMatrix b) { return fromSparseToMatrix(a, b); } private Matrix fromSparseToMatrix(SparseMatrix a, Matrix b) { MatrixIterator it = a.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); b.set(i, j, x); } return b; } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/000077500000000000000000000000001263320764000220515ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceInnerProduct.java000066400000000000000000000044161263320764000266000ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.operation.SymmetricVectorVectorOperation; import org.la4j.Vector; import org.la4j.iterator.VectorIterator; import org.la4j.Vectors; import org.la4j.vector.DenseVector; import org.la4j.vector.functor.VectorFunction; import org.la4j.vector.SparseVector; public class OoPlaceInnerProduct extends SymmetricVectorVectorOperation { @Override public Double apply(final SparseVector a, final SparseVector b) { VectorIterator these = a.nonZeroIterator(); VectorIterator those = b.nonZeroIterator(); return these.innerProduct(those); } @Override public Double applySymmetric(DenseVector a, SparseVector b) { return b.foldNonZero(Vectors.asSumFunctionAccumulator(0.0, dot(a))); } @Override public Double apply(final DenseVector a, final DenseVector b) { double result = 0.0; for (int i = 0; i < a.length(); i++) { result += a.get(i) * b.get(i); } return result; } private VectorFunction dot(final Vector b) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return b.get(i) * value; } }; } @Override public void ensureApplicableTo(Vector a, Vector b) { if (a.length() != b.length()) { throw new IllegalArgumentException( "Given vectors should have the same length: " + a.length() + " does not equal to " + b.length() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceKroneckerProduct.java000066400000000000000000000012761263320764000274510ustar00rootroot00000000000000package org.la4j.operation.ooplace; import org.la4j.Matrix; import org.la4j.operation.CommonMatrixMatrixOperation; public class OoPlaceKroneckerProduct extends CommonMatrixMatrixOperation { // TODO: It should not be common. @Override public Matrix applyCommon(Matrix a, Matrix b) { int n = a.rows() * b.rows(); int m = a.columns() * b.columns(); int p = b.rows(); int q = b.columns(); Matrix result = a.blankOfShape(n, m); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { result.set(i, j, a.get(i / p, j / q) * b.get(i % p, j % q)); } } return result; } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceMatricesAddition.java000066400000000000000000000064121263320764000274050ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.iterator.MatrixIterator; import org.la4j.iterator.RowMajorMatrixIterator; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.operation.SymmetricMatrixMatrixOperation; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.matrix.SparseMatrix; public class OoPlaceMatricesAddition extends SymmetricMatrixMatrixOperation { @Override public Matrix applySymmetric(DenseMatrix a, SparseMatrix b) { Matrix result = a.copy(); MatrixIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, result.get(i, j) + x); } return result; } @Override public Matrix applySymmetric(RowMajorSparseMatrix a, ColumnMajorSparseMatrix b) { Matrix result = a.blank(); RowMajorMatrixIterator these = a.nonZeroRowMajorIterator(); RowMajorMatrixIterator those = b.nonZeroRowMajorIterator(); MatrixIterator both = these.orElseAdd(those); while (both.hasNext()) { double x = both.next(); int i = both.rowIndex(); int j = both.columnIndex(); result.set(i, j, x); } return result; } @Override public Matrix apply(DenseMatrix a, DenseMatrix b) { Matrix result = a.blank(); for (int i = 0; i < a.rows(); i++) { for (int j = 0; j < a.columns(); j++) { result.set(i, j, a.get(i, j) + b.get(i, j)); } } return result; } @Override public Matrix applySymmetric(SparseMatrix a, SparseMatrix b) { Matrix result = a.blank(); MatrixIterator these = a.nonZeroIterator(); MatrixIterator those = b.nonZeroIterator(); MatrixIterator both = these.orElseAdd(those); while (both.hasNext()) { double x = both.next(); int i = both.rowIndex(); int j = both.columnIndex(); result.set(i, j, x); } return result; } @Override public void ensureApplicableTo(Matrix a, Matrix b) { if (a.rows() != b.rows() || a.columns() != b.columns()) { throw new IllegalArgumentException( "Given matrices should have the same shape: " + a.rows() + "x" + a.columns() + " does not equal to " + b.rows() + "x" + b.columns() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceMatricesMultiplication.java000066400000000000000000000152051263320764000306470ustar00rootroot00000000000000package org.la4j.operation.ooplace; import org.la4j.iterator.MatrixIterator; import org.la4j.iterator.VectorIterator; import org.la4j.Matrices; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.operation.MatrixMatrixOperation; import org.la4j.Vector; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class OoPlaceMatricesMultiplication extends MatrixMatrixOperation { @Override public Matrix apply(DenseMatrix a, DenseMatrix b) { Matrix result = a.blankOfShape(a.rows(), b.columns()); for (int j = 0; j < b.columns(); j++) { Vector column = b.getColumn(j); for (int i = 0; i < a.rows(); i++) { double acc = 0.0; for (int k = 0; k < a.columns(); k++) { acc += a.get(i, k) * column.get(k); } result.set(i, j, acc); } } return result; } @Override public Matrix apply(DenseMatrix a, RowMajorSparseMatrix b) { Matrix result = ColumnMajorSparseMatrix.zero(a.rows(), b.columns()); MatrixIterator it = b.nonZeroRowMajorIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); for (int k = 0; k < a.rows(); k++) { result.updateAt(k, j, Matrices.asPlusFunction(x * a.get(k, i))); } } return result; } @Override public Matrix apply(DenseMatrix a, ColumnMajorSparseMatrix b) { Matrix result = b.blankOfShape(a.rows(), b.columns()); Iterator nzColumns = b.iteratorOrNonZeroColumns(); while (nzColumns.hasNext()) { int j = nzColumns.next(); for (int i = 0; i < a.rows(); i++) { double acc = 0.0; VectorIterator it = b.nonZeroIteratorOfColumn(j); while (it.hasNext()) { double x = it.next(); acc += x * a.get(i, it.index()); } result.set(i, j, acc); } } return result; } @Override public Matrix apply(RowMajorSparseMatrix a, DenseMatrix b) { Matrix result = a.blankOfShape(a.rows(), b.columns()); Iterator nzRows = a.iteratorOfNonZeroRows(); while (nzRows.hasNext()) { int i = nzRows.next(); for (int j = 0; j < b.columns(); j++) { double acc = 0.0; VectorIterator it = a.nonZeroIteratorOfRow(i); while (it.hasNext()) { double x = it.next(); acc += x * b.get(it.index(), j); } result.set(i, j, acc); } } return result; } @Override public Matrix apply(RowMajorSparseMatrix a, RowMajorSparseMatrix b) { // TODO: Can we do it w/o updateAt? Matrix result = a.blankOfShape(a.rows(), b.columns()); MatrixIterator these = a.nonZeroRowMajorIterator(); while (these.hasNext()) { double x = these.next(); int i = these.rowIndex(); int j = these.columnIndex(); VectorIterator those = b.nonZeroIteratorOfRow(j); while (those.hasNext()) { double y = those.next(); int k = those.index(); result.updateAt(i, k, Matrices.asPlusFunction(x * y)); } } return result; } @Override public Matrix apply(RowMajorSparseMatrix a, ColumnMajorSparseMatrix b) { Matrix result = a.blankOfShape(a.rows(), b.columns()); Iterator nzRows = a.iteratorOfNonZeroRows(); Iterator nzColumnsIt = b.iteratorOrNonZeroColumns(); List nzColumns = new ArrayList(); while(nzColumnsIt.hasNext()) { nzColumns.add(nzColumnsIt.next()); } while(nzRows.hasNext()) { int i = nzRows.next(); for (int j: nzColumns) { result.set(i, j, a.nonZeroIteratorOfRow(i) .innerProduct(b.nonZeroIteratorOfColumn(j))); } } return result; } @Override public Matrix apply(ColumnMajorSparseMatrix a, DenseMatrix b) { Matrix result = a.blankOfShape(a.rows(), b.columns()); MatrixIterator it = a.nonZeroColumnMajorIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); for (int k = 0; k < b.columns(); k++) { result.updateAt(i, k, Matrices.asPlusFunction(x * b.get(j, k))); } } return result; } @Override public Matrix apply(ColumnMajorSparseMatrix a, RowMajorSparseMatrix b) { // TODO: Might be improved a bit. Matrix result = b.blankOfShape(a.rows(), b.columns()); MatrixIterator these = a.nonZeroColumnMajorIterator(); while (these.hasNext()) { double x = these.next(); int i = these.rowIndex(); int j = these.columnIndex(); VectorIterator those = b.nonZeroIteratorOfRow(j); while (those.hasNext()) { double y = those.next(); int k = those.index(); result.updateAt(i, k, Matrices.asPlusFunction(x * y)); } } return result; } @Override public Matrix apply(ColumnMajorSparseMatrix a, ColumnMajorSparseMatrix b) { // TODO: Might be improved a bit. Matrix result = a.blankOfShape(a.rows(), b.columns()); MatrixIterator these = b.nonZeroColumnMajorIterator(); while (these.hasNext()) { double x = these.next(); int i = these.rowIndex(); int j = these.columnIndex(); VectorIterator those = a.nonZeroIteratorOfColumn(i); while (those.hasNext()) { double y = those.next(); int k = those.index(); result.updateAt(k, j, Matrices.asPlusFunction(x * y)); } } return result; } @Override public void ensureApplicableTo(Matrix a, Matrix b) { if (a.columns() != b.rows()) { throw new IllegalArgumentException( "The number of rows in the left-hand matrix should be equal to the number of " + "columns in the right-hand matrix: " + a.rows() + " does not equal to " + b.columns() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceMatricesSubtraction.java000066400000000000000000000101451263320764000301450ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.iterator.MatrixIterator; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.operation.SimpleMatrixMatrixOperation; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.matrix.SparseMatrix; public class OoPlaceMatricesSubtraction extends SimpleMatrixMatrixOperation { @Override public Matrix apply(DenseMatrix a, DenseMatrix b) { Matrix result = a.blank(); for (int i = 0; i < a.rows(); i++) { for (int j = 0; j < a.columns(); j++) { result.set(i, j, a.get(i, j) - b.get(i, j)); } } return result; } @Override public Matrix applySimple(DenseMatrix a, SparseMatrix b) { Matrix result = a.copy(); MatrixIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, result.get(i, j) - x); } return result; } @Override public Matrix applySimple(SparseMatrix a, DenseMatrix b) { Matrix result = b.multiply(-1.0); MatrixIterator it = a.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, result.get(i, j) + x); } return result; } @Override public Matrix applySimple(SparseMatrix a, SparseMatrix b) { Matrix result = a.blank(); MatrixIterator these = a.nonZeroIterator(); MatrixIterator those = b.nonZeroIterator(); MatrixIterator both = these.orElseSubtract(those); while (both.hasNext()) { double x = both.next(); int i = both.rowIndex(); int j = both.columnIndex(); result.set(i, j, x); } return result; } @Override public Matrix apply(RowMajorSparseMatrix a, ColumnMajorSparseMatrix b) { Matrix result = a.blank(); MatrixIterator these = a.nonZeroRowMajorIterator(); MatrixIterator those = b.nonZeroRowMajorIterator(); MatrixIterator both = these.orElseSubtract(those); while (both.hasNext()) { double x = both.next(); int i = both.rowIndex(); int j = both.columnIndex(); result.set(i, j, x); } return result; } @Override public Matrix apply(ColumnMajorSparseMatrix a, RowMajorSparseMatrix b) { Matrix result = a.blank(); MatrixIterator these = a.nonZeroColumnMajorIterator(); MatrixIterator those = b.nonZeroColumnMajorIterator(); MatrixIterator both = these.orElseSubtract(those); while (both.hasNext()) { double x = both.next(); int i = both.rowIndex(); int j = both.columnIndex(); result.set(i, j, x); } return result; } @Override public void ensureApplicableTo(Matrix a, Matrix b) { if (a.rows() != b.rows() || a.columns() != b.columns()) { throw new IllegalArgumentException( "Given matrices should have the same shape: " + a.rows() + "x" + a.columns() + " does not equal to " + b.rows() + "x" + b.columns() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceMatrixByItsTransposeMultiplication.java000066400000000000000000000031131263320764000332110ustar00rootroot00000000000000package org.la4j.operation.ooplace; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.operation.MatrixOperation; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class OoPlaceMatrixByItsTransposeMultiplication extends MatrixOperation { @Override public Matrix apply(DenseMatrix a) { Matrix result = a.blankOfShape(a.rows(), a.rows()); for (int i = 0; i < a.rows(); i++) { for (int j = 0; j < a.rows(); j++) { double acc = 0.0; for (int k = 0; k < a.columns(); k++) { acc += a.get(i, k) * a.get(j, k); } result.set(i, j, acc); } } return result; } @Override public Matrix apply(RowMajorSparseMatrix a) { Matrix result = a.blankOfShape(a.rows(), a.rows()); List nzRows = new ArrayList(); Iterator it = a.iteratorOfNonZeroRows(); while (it.hasNext()) { nzRows.add(it.next()); } for (int i: nzRows) { for (int j: nzRows) { result.set(i, j, a.nonZeroIteratorOfRow(i) .innerProduct(a.nonZeroIteratorOfRow(j))); } } return result; } @Override public Matrix apply(ColumnMajorSparseMatrix a) { // TODO: Implement its own algorithm return apply(a.toRowMajorSparseMatrix()); } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceMatrixByVectorMultiplication.java000066400000000000000000000104721263320764000320230ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.iterator.MatrixIterator; import org.la4j.iterator.VectorIterator; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.operation.MatrixVectorOperation; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; import java.util.Iterator; public class OoPlaceMatrixByVectorMultiplication extends MatrixVectorOperation { @Override public Vector apply(DenseMatrix a, DenseVector b) { Vector result = b.blankOfLength(a.rows()); for (int i = 0; i < a.rows(); i++) { double acc = 0.0; for (int j = 0; j < a.columns(); j++) { acc += a.get(i, j) * b.get(j); } result.set(i, acc); } return result; } @Override public Vector apply(DenseMatrix a, SparseVector b) { Vector result = DenseVector.zero(a.rows()); for (int i = 0; i < a.rows(); i++) { double acc = 0.0; VectorIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int j = it.index(); acc += a.get(i, j) * x; } result.set(i, acc); } return result; } @Override public Vector apply(RowMajorSparseMatrix a, DenseVector b) { Vector result = DenseVector.zero(a.rows()); MatrixIterator it = a.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, result.get(i) + (x * b.get(j))); } return result; } @Override public Vector apply(RowMajorSparseMatrix a, SparseVector b) { Vector result = b.blankOfLength(a.rows()); Iterator it = a.iteratorOfNonZeroRows(); while (it.hasNext()) { int i = it.next(); VectorIterator these = a.nonZeroIteratorOfRow(i); VectorIterator those = b.nonZeroIterator(); result.set(i, these.innerProduct(those)); } return result; } @Override public Vector apply(ColumnMajorSparseMatrix a, DenseVector b) { Vector result = DenseVector.zero(a.rows()); MatrixIterator it = a.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, result.get(i) + (x * b.get(j))); } return result; } @Override public Vector apply(ColumnMajorSparseMatrix a, SparseVector b) { Vector result = b.blankOfLength(a.rows()); VectorIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int j = it.index(); VectorIterator these = a.nonZeroIteratorOfColumn(j); while (these.hasNext()) { double y = these.next(); int i = these.index(); result.updateAt(i, Vectors.asPlusFunction(x * y)); } } return result; } @Override public void ensureApplicableTo(Matrix a, Vector b) { if (a.columns() != b.length()) { throw new IllegalArgumentException( "Given vector should have the same length as number of columns in the given matrix: " + b.length() + " does not equal to " + a.columns() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceMatrixHadamardProduct.java000066400000000000000000000064301263320764000304110ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.iterator.MatrixIterator; import org.la4j.iterator.RowMajorMatrixIterator; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.operation.SymmetricMatrixMatrixOperation; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.matrix.SparseMatrix; public class OoPlaceMatrixHadamardProduct extends SymmetricMatrixMatrixOperation { @Override public Matrix applySymmetric(DenseMatrix a, SparseMatrix b) { Matrix result = b.blank(); MatrixIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.set(i, j, a.get(i, j) * x); } return result; } @Override public Matrix applySymmetric(SparseMatrix a, SparseMatrix b) { Matrix result = a.blank(); MatrixIterator these = a.nonZeroIterator(); MatrixIterator those = b.nonZeroIterator(); MatrixIterator both = these.andAlsoMultiply(those); while (both.hasNext()) { double x = both.next(); int i = both.rowIndex(); int j = both.columnIndex(); result.set(i, j, x); } return result; } @Override public Matrix applySymmetric(RowMajorSparseMatrix a, ColumnMajorSparseMatrix b) { Matrix result = a.blank(); RowMajorMatrixIterator these = a.nonZeroRowMajorIterator(); RowMajorMatrixIterator those = b.nonZeroRowMajorIterator(); MatrixIterator both = these.andAlsoMultiply(those); while (both.hasNext()) { double x = both.next(); int i = both.rowIndex(); int j = both.columnIndex(); result.set(i, j, x); } return result; } @Override public Matrix apply(DenseMatrix a, DenseMatrix b) { Matrix result = a.blank(); for (int i = 0; i < a.rows(); i++) { for (int j = 0; j < a.columns(); j++) { result.set(i, j, a.get(i, j) * b.get(i, j)); } } return result; } @Override public void ensureApplicableTo(Matrix a, Matrix b) { if (a.rows() != b.rows() || a.columns() != b.columns()) { throw new IllegalArgumentException( "Given matrices should have the same shape: " + a.rows() + "x" + a.columns() + " does not equal to " + b.rows() + "x" + b.columns() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceOuterProduct.java000066400000000000000000000056241263320764000266250ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.iterator.VectorIterator; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.vector.DenseVector; import org.la4j.operation.VectorVectorOperation; import org.la4j.vector.SparseVector; public class OoPlaceOuterProduct extends VectorVectorOperation { @Override public Matrix apply(SparseVector a, SparseVector b) { Matrix result = RowMajorSparseMatrix.zero(a.length(), b.length()); VectorIterator these = a.nonZeroIterator(); while (these.hasNext()) { double x = these.next(); int i = these.index(); VectorIterator those = b.nonZeroIterator(); while (those.hasNext()) { double y = those.next(); int j = those.index(); result.set(i, j, x * y); } } return result; } @Override public Matrix apply(DenseVector a, DenseVector b) { Matrix result = DenseMatrix.zero(a.length(), b.length()); for (int i = 0; i < a.length(); i++) { for (int j = 0; j < b.length(); j++) { result.set(i, j, a.get(i) * b.get(j)); } } return result; } @Override public Matrix apply(DenseVector a, SparseVector b) { Matrix result = ColumnMajorSparseMatrix.zero(a.length(), b.length()); VectorIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int j = it.index(); for (int i = 0; i < a.length(); i++) { result.set(i, j, x * a.get(i)); } } return result; } @Override public Matrix apply(SparseVector a, DenseVector b) { Matrix result = RowMajorSparseMatrix.zero(a.length(), b.length()); VectorIterator it = a.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); for (int j = 0; j < b.length(); j++) { result.set(i, j, x * b.get(j)); } } return result; } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceVectorByMatrixMultiplication.java000066400000000000000000000111551263320764000320220ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.iterator.MatrixIterator; import org.la4j.iterator.VectorIterator; import org.la4j.Matrix; import org.la4j.matrix.DenseMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.vector.DenseVector; import org.la4j.operation.VectorMatrixOperation; import org.la4j.vector.SparseVector; import java.util.Iterator; public class OoPlaceVectorByMatrixMultiplication extends VectorMatrixOperation { @Override public Vector apply(SparseVector a, DenseMatrix b) { Vector result = DenseVector.zero(b.columns()); for (int j = 0; j < b.columns(); j++) { double acc = 0.0; VectorIterator it = a.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); acc += x * b.get(i, j); } result.set(j, acc); } return result; } @Override public Vector apply(SparseVector a, RowMajorSparseMatrix b) { // TODO: use sequential writes Vector result = a.blankOfLength(b.columns()); VectorIterator these = a.nonZeroIterator(); while (these.hasNext()) { double x = these.next(); int i = these.index(); VectorIterator those = b.iteratorOfRow(i); while (those.hasNext()) { double y = those.next(); int j = those.index(); result.updateAt(j, Vectors.asPlusFunction(x * y)); } } return result; } @Override public Vector apply(SparseVector a, ColumnMajorSparseMatrix b) { Vector result = a.blankOfLength(b.columns()); Iterator columns = b.iteratorOrNonZeroColumns(); while (columns.hasNext()) { int j = columns.next(); VectorIterator these = a.nonZeroIterator(); VectorIterator those = b.nonZeroIteratorOfColumn(j); result.set(j, these.innerProduct(those)); } return result; } @Override public Vector apply(DenseVector a, DenseMatrix b) { Vector result = a.blankOfLength(b.columns()); for (int j = 0; j < b.columns(); j++) { double acc = 0.0; for (int i = 0; i < b.rows(); i++) { acc += a.get(i) * b.get(i, j); } result.set(j, acc); } return result; } @Override public Vector apply(DenseVector a, RowMajorSparseMatrix b) { // TODO: use sequential writes Vector result = SparseVector.zero(b.columns()); MatrixIterator it = b.rowMajorIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); result.updateAt(j, Vectors.asPlusFunction(x * a.get(i))); } return result; } @Override public Vector apply(DenseVector a, ColumnMajorSparseMatrix b) { Vector result = SparseVector.zero(b.columns()); Iterator columns = b.iteratorOrNonZeroColumns(); while (columns.hasNext()) { int j = columns.next(); VectorIterator it = b.nonZeroIteratorOfColumn(j); double acc = 0.0; while (it.hasNext()) { double x = it.next(); int i = it.index(); acc += x * a.get(i); } result.set(j, acc); } return result; } @Override public void ensureApplicableTo(Vector a, Matrix b) { if (a.length() != b.rows()) { throw new IllegalArgumentException( "Given vector should have the same length as number of rows in the given matrix: " + a.length() + " does not equal to " + b.rows() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceVectorHadamardProduct.java000066400000000000000000000045401263320764000304070ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.iterator.VectorIterator; import org.la4j.operation.SymmetricVectorVectorOperation; import org.la4j.Vector; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public class OoPlaceVectorHadamardProduct extends SymmetricVectorVectorOperation { @Override public Vector apply(SparseVector a, SparseVector b) { VectorIterator these = a.nonZeroIterator(); VectorIterator those = b.nonZeroIterator(); VectorIterator both = these.andAlsoMultiply(those); Vector result = a.blank(); while (both.hasNext()) { double x = both.next(); int i = both.index(); result.set(i, x); } return result; } @Override public Vector apply(DenseVector a, DenseVector b) { Vector result = a.blank(); for (int i = 0; i < a.length(); i++) { result.set(i, a.get(i) * b.get(i)); } return result; } @Override public Vector applySymmetric(DenseVector a, SparseVector b) { Vector result = b.blank(); VectorIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, x * a.get(i)); } return result; } @Override public void ensureApplicableTo(Vector a, Vector b) { if (a.length() != b.length()) { throw new IllegalArgumentException( "Given vectors should have the same length: " + a.length() + " does not equal to " + b.length() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceVectorsAddition.java000066400000000000000000000045311263320764000272630ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.operation.SymmetricVectorVectorOperation; import org.la4j.Vector; import org.la4j.iterator.VectorIterator; import org.la4j.vector.DenseVector; import org.la4j.vector.SparseVector; public class OoPlaceVectorsAddition extends SymmetricVectorVectorOperation { @Override public Vector apply(SparseVector a, SparseVector b) { VectorIterator these = a.nonZeroIterator(); VectorIterator those = b.nonZeroIterator(); VectorIterator both = these.orElseAdd(those); Vector result = a.blank(); while (both.hasNext()) { double x = both.next(); int i = both.index(); result.set(i, x); } return result; } @Override public Vector apply(DenseVector a, DenseVector b) { Vector result = a.blank(); for (int i = 0; i < a.length(); i++) { result.set(i, a.get(i) + b.get(i)); } return result; } @Override public Vector applySymmetric(DenseVector a, SparseVector b) { Vector result = a.copy(); VectorIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, result.get(i) + x); } return result; } @Override public void ensureApplicableTo(Vector a, Vector b) { if (a.length() != b.length()) { throw new IllegalArgumentException( "Given vectors should have the same length: " + a.length() + " does not equal to " + b.length() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/operation/ooplace/OoPlaceVectorsSubtraction.java000066400000000000000000000052401263320764000300230ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.operation.ooplace; import org.la4j.iterator.VectorIterator; import org.la4j.Vector; import org.la4j.vector.DenseVector; import org.la4j.operation.VectorVectorOperation; import org.la4j.vector.SparseVector; public class OoPlaceVectorsSubtraction extends VectorVectorOperation { @Override public Vector apply(SparseVector a, SparseVector b) { VectorIterator these = a.nonZeroIterator(); VectorIterator those = b.nonZeroIterator(); VectorIterator both = these.orElseSubtract(those); Vector result = a.blank(); while (both.hasNext()) { double x = both.next(); int i = both.index(); result.set(i, x); } return result; } @Override public Vector apply(SparseVector a, DenseVector b) { Vector result = b.multiply(-1.0); VectorIterator it = a.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, result.get(i) + x); } return result; } @Override public Vector apply(DenseVector a, DenseVector b) { Vector result = a.blank(); for (int i = 0; i < b.length(); i++) { result.set(i, a.get(i) - b.get(i)); } return result; } @Override public Vector apply(DenseVector a, SparseVector b) { Vector result = a.copy(); VectorIterator it = b.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, result.get(i) - x); } return result; } @Override public void ensureApplicableTo(Vector a, Vector b) { if (a.length() != b.length()) { throw new IllegalArgumentException( "Given vectors should have the same length: " + a.length() + " does not equal to " + b.length() + "." ); } } } la4j-0.6.0/src/main/java/org/la4j/vector/000077500000000000000000000000001263320764000177315ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/vector/DenseVector.java000066400000000000000000000133171263320764000230220ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector; import org.la4j.Matrix; import org.la4j.Vectors; import org.la4j.matrix.dense.Basic2DMatrix; import org.la4j.Vector; import org.la4j.operation.VectorMatrixOperation; import org.la4j.operation.VectorOperation; import org.la4j.operation.VectorVectorOperation; import org.la4j.vector.dense.BasicVector; import java.text.NumberFormat; import java.util.Collection; import java.util.Map; import java.util.Random; /** * A dense vector. * * A vector represents an array of elements. It can be re-sized. * * A dense data structure usually stores data in an underlying array. Zero elements * take up memory space. If you want a data structure that will not have zero * elements take up memory space, try a sparse structure. * * However, fetch/store operations on dense data structures only take O(1) time, * instead of the O(log n) time on sparse structures. * */ public abstract class DenseVector extends Vector { /** * Creates a zero {@link DenseVector} of the given {@code length}. */ public static DenseVector zero(int length) { return BasicVector.zero(length); } /** * Creates a constant {@link DenseVector} of the given {@code length} with * the given {@code value}. */ public static DenseVector constant(int length, double value) { return BasicVector.constant(length, value); } /** * Creates an unit {@link DenseVector} of the given {@code length}. */ public static DenseVector unit(int length) { return DenseVector.constant(length, 1.0); } /** * Creates a random {@link DenseVector} of the given {@code length} with * the given {@code Random}. */ public static DenseVector random(int length, Random random) { return BasicVector.random(length, random); } /** * Creates a new {@link DenseVector} from the given {@code array} w/o * copying the underlying array. */ public static DenseVector fromArray(double[] array) { return BasicVector.fromArray(array); } /** * Parses {@link DenseVector} from the given CSV string. * * @param csv the CSV string representing a vector * * @return a parsed vector */ public static DenseVector fromCSV(String csv) { return Vector.fromCSV(csv).to(Vectors.DENSE); } /** * Parses {@link DenseVector} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed vector */ public static DenseVector fromMatrixMarket(String mm) { return Vector.fromMatrixMarket(mm).to(Vectors.DENSE); } /** * Creates new {@link org.la4j.vector.DenseVector} from * * @param list list containing doubles * * @return new vector from given double list */ public static DenseVector fromCollection(Collection list) { return BasicVector.fromCollection(list); } /** * Creates new {@link DenseVector} from index-value map * * @param map index-value map * * @param length vector length * * @return created vector */ public static DenseVector fromMap(Map map, int length) { return Vector.fromMap(map, length).to(Vectors.DENSE); } @Override public T apply(VectorOperation operation) { operation.ensureApplicableTo(this); return operation.apply(this); } @Override public T apply(VectorVectorOperation operation, Vector that) { return that.apply(operation.partiallyApply(this)); } @Override public T apply(VectorMatrixOperation operation, Matrix that) { return that.apply(operation.partiallyApply(this)); } /** * Converts this dense vector to a double array. * * @return an array representation of this vector */ public abstract double[] toArray(); public DenseVector(int length) { super(length); } @Override public Matrix toRowMatrix() { Matrix result = Basic2DMatrix.zero(1, length); for (int j = 0; j < length; j++) { result.set(0, j, get(j)); } return result; } @Override public Matrix toColumnMatrix() { Matrix result = Basic2DMatrix.zero(length, 1); for (int i = 0; i < length; i++) { result.set(i, 0, get(i)); } return result; } @Override public Matrix toDiagonalMatrix() { Matrix result = Basic2DMatrix.zero(length, length); for (int i = 0; i < length; i++) { result.set(i, i, get(i)); } return result; } @Override public String toMatrixMarket(NumberFormat formatter) { StringBuilder out = new StringBuilder(); out.append("%%MatrixMarket vector array real\n"); out.append(length).append('\n'); for (int i = 0; i < length; i++) { out.append(formatter.format(get(i))).append('\n'); } return out.toString(); } } la4j-0.6.0/src/main/java/org/la4j/vector/SparseVector.java000066400000000000000000000256071263320764000232260ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector; import java.text.NumberFormat; import java.util.Collection; import java.util.Map; import java.util.Random; import org.la4j.iterator.VectorIterator; import org.la4j.Matrix; import org.la4j.matrix.sparse.CRSMatrix; import org.la4j.matrix.ColumnMajorSparseMatrix; import org.la4j.matrix.RowMajorSparseMatrix; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.vector.functor.VectorAccumulator; import org.la4j.vector.functor.VectorProcedure; import org.la4j.operation.VectorMatrixOperation; import org.la4j.operation.VectorOperation; import org.la4j.operation.VectorVectorOperation; import org.la4j.vector.sparse.CompressedVector; /** * A sparse vector. * * A vector represents an array of elements. It can be re-sized. * * A sparse data structure does not store blank elements, and instead just stores * elements with values. A sparse data structure can be initialized with a large * length but take up no storage until the space is filled with non-zero elements. * * However, there is a performance cost. Fetch/store operations take O(log n) * time instead of the O(1) time of a dense data structure. * */ public abstract class SparseVector extends Vector { /** * Creates a zero {@link SparseVector} of the given {@code length}. */ public static SparseVector zero(int length) { return CompressedVector.zero(length); } /** * Creates a zero {@link SparseVector} of the given {@code length} with * the given {@code capacity}. */ public static SparseVector zero(int length, int capacity) { return CompressedVector.zero(length); } /** * Creates a constant {@link SparseVector} of the given {@code length} with * the given {@code value}. */ public static SparseVector random(int length, double density, Random random) { return CompressedVector.random(length, density, random); } /** * Creates a new {@link SparseVector} from the given {@code array} with * compressing (copying) the underlying array. */ public static SparseVector fromArray(double[] array) { return CompressedVector.fromArray(array); } /** * Parses {@link SparseVector} from the given CSV string. * * @param csv the CSV string representing a vector * * @return a parsed vector */ public static SparseVector fromCSV(String csv) { return Vector.fromCSV(csv).to(Vectors.SPARSE); } /** * Parses {@link SparseVector} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed vector */ public static SparseVector fromMatrixMarket(String mm) { return Vector.fromMatrixMarket(mm).to(Vectors.SPARSE); } /** * Creates new {@link SparseVector} from collection * * @param list value list * * @return created vector */ public static SparseVector fromCollection(Collection list) { return Vector.fromCollection(list).to(Vectors.SPARSE); } /** * Creates new {@link SparseVector} from given index-value map * * @param map * * @return */ public static SparseVector fromMap(Map map, int length) { return CompressedVector.fromMap(map, length); } protected int cardinality; public SparseVector(int length) { this(length, 0); } public SparseVector(int length, int cardinality) { super(length); this.cardinality = cardinality; } /** * Returns the cardinality (the number of non-zero elements) * of this sparse vector. * * @return the cardinality of this vector */ public int cardinality() { return cardinality; } /** * Returns the density (non-zero elements divided by total elements) * of this sparse vector. * * @return the density of this vector */ public double density() { return cardinality / (double) length; } @Override public double get(int i) { return getOrElse(i, 0.0); } /** * Gets the specified element, or a {@code defaultValue} if there * is no actual element at index {@code i} in this sparse vector. * * @param i the element's index * @param defaultValue the default value * * @return the element of this vector or a default value */ public abstract double getOrElse(int i, double defaultValue); /** * Whether or not the specified element is zero. * * @param i element's index * * @return {@code true} if specified element is zero, {@code false} otherwise */ public boolean isZeroAt(int i) { return !nonZeroAt(i); } /** * * Whether or not the specified element is not zero. * * @param i element's index * * @return {@code true} if specified element is zero, {@code false} otherwise */ public abstract boolean nonZeroAt(int i); /** * Folds non-zero elements of this vector with given {@code accumulator}. * * @param accumulator the vector accumulator * * @return the accumulated value */ public double foldNonZero(VectorAccumulator accumulator) { eachNonZero(Vectors.asAccumulatorProcedure(accumulator)); return accumulator.accumulate(); } /** * Applies given {@code procedure} to each non-zero element of this vector. * * @param procedure the vector procedure */ public void eachNonZero(VectorProcedure procedure) { VectorIterator it = nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); procedure.apply(i, x); } } @Override public Vector add(double value) { Vector result = DenseVector.constant(length, value); VectorIterator it = nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, x + value); } return result; } @Override public Vector multiply(double value) { Vector result = blank(); VectorIterator it = nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, x * value); } return result; } @Override public double max() { double max = foldNonZero(Vectors.mkMaxAccumulator()); return (max > 0.0) ? max : 0.0; } @Override public double min() { double min = foldNonZero(Vectors.mkMinAccumulator()); return (min < 0.0) ? min : 0.0; } @Override public double euclideanNorm() { return foldNonZero(Vectors.mkEuclideanNormAccumulator()); } @Override public double manhattanNorm() { return foldNonZero(Vectors.mkManhattanNormAccumulator()); } @Override public double infinityNorm() { double norm = foldNonZero(Vectors.mkInfinityNormAccumulator()); return (norm > 0.0) ? norm : 0.0; } /** * Returns a non-zero vector iterator. * * @return a non-zero vector iterator */ public abstract VectorIterator nonZeroIterator(); @Override public T to(VectorFactory factory) { T result = factory.apply(length); VectorIterator it = nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, x); } return result; } @Override public int hashCode() { int result = 17; VectorIterator it = nonZeroIterator(); while (it.hasNext()) { long x = it.next().longValue(); long i = (long) it.index(); result = 37 * result + (int) (x ^ (x >>> 32)); result = 37 * result + (int) (i ^ (i >>> 32)); } return result; } @Override public T apply(VectorOperation operation) { operation.ensureApplicableTo(this); return operation.apply(this); } @Override public T apply(VectorVectorOperation operation, Vector that) { return that.apply(operation.partiallyApply(this)); } @Override public T apply(VectorMatrixOperation operation, Matrix that) { return that.apply(operation.partiallyApply(this)); } @Override public Matrix toRowMatrix() { VectorIterator it = nonZeroIterator(); Matrix result = CRSMatrix.zero(1, length); while (it.hasNext()) { double x = it.next(); int j = it.index(); result.set(0, j, x); } return result; } @Override public Matrix toColumnMatrix() { VectorIterator it = nonZeroIterator(); Matrix result = ColumnMajorSparseMatrix.zero(length, 1); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, 0, x); } return result; } @Override public Matrix toDiagonalMatrix() { VectorIterator it = nonZeroIterator(); Matrix result = RowMajorSparseMatrix.zero(length, length); while (it.hasNext()) { double x = it.next(); int i = it.index(); result.set(i, i, x); } return result; } @Override public String toMatrixMarket(NumberFormat formatter) { StringBuilder out = new StringBuilder(); VectorIterator it = nonZeroIterator(); out.append("%%MatrixMarket vector coordinate real\n"); out.append(length).append(' ').append(cardinality).append('\n'); while (it.hasNext()) { double x = it.next(); int i = it.index(); out.append(i + 1).append(' ').append(formatter.format(x)).append('\n'); } return out.toString(); } /** * Ensures the provided index is in the bounds of this {@link SparseVector}. * * @param i The index to check. */ protected void ensureIndexIsInBounds(int i) { if (i < 0 || i >= length) { throw new IndexOutOfBoundsException("Index '" + i + "' is invalid."); } } } la4j-0.6.0/src/main/java/org/la4j/vector/VectorFactory.java000066400000000000000000000022331263320764000233660ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of the la4j project (http://la4j.org) * * 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. * * Contributor(s): */ package org.la4j.vector; import org.la4j.Vector; import java.lang.reflect.ParameterizedType; /** * An abstract vector factory. * * @param */ public abstract class VectorFactory { @SuppressWarnings("unchecked cast") public final Class outputClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; /** * */ public abstract T apply(int length); } la4j-0.6.0/src/main/java/org/la4j/vector/dense/000077500000000000000000000000001263320764000210275ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/vector/dense/BasicVector.java000066400000000000000000000154471263320764000241110ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.dense; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Random; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.vector.DenseVector; import org.la4j.vector.VectorFactory; /** * A basic dense vector implementation using an array. * * A dense data structure stores data in an underlying array. Even zero elements * take up memory space. If you want a data structure that will not have zero * elements take up memory space, try a sparse structure. * * However, fetch/store operations on dense data structures only take O(1) time, * instead of the O(log n) time on sparse structures. * * {@code BasicVector} stores the underlying data in a standard array. */ public class BasicVector extends DenseVector { private static final byte VECTOR_TAG = (byte) 0x00; /** * Creates a zero {@link BasicVector} of the given {@code length}. */ public static BasicVector zero(int length) { return new BasicVector(length); } /** * Creates a constant {@link BasicVector} of the given {@code length} with * the given {@code value}. */ public static BasicVector constant(int length, double value) { double array[] = new double[length]; Arrays.fill(array, value); return new BasicVector(array); } /** * Creates an unit {@link BasicVector} of the given {@code length}. */ public static BasicVector unit(int length) { return BasicVector.constant(length, 1.0); } /** * Creates a random {@link BasicVector} of the given {@code length} with * the given {@code Random}. */ public static BasicVector random(int length, Random random) { double array[] = new double[length]; for (int i = 0; i < length; i++) { array[i] = random.nextDouble(); } return new BasicVector(array); } /** * Creates a new {@link BasicVector} from the given {@code array} w/o * copying the underlying array. */ public static BasicVector fromArray(double[] array) { return new BasicVector(array); } /** * Decodes {@link BasicVector} from the given byte {@code array}. * * @param array the byte array representing a vector * * @return a decoded vector */ public static BasicVector fromBinary(byte[] array) { ByteBuffer buffer = ByteBuffer.wrap(array); if (buffer.get() != VECTOR_TAG) { throw new IllegalArgumentException("Can not decode BasicVector from the given byte array."); } double[] values = new double[buffer.getInt()]; for (int i = 0; i < values.length; i++) { values[i] = buffer.getDouble(); } return new BasicVector(values); } /** * Parses {@link BasicVector} from the given CSV string. * * @param csv the CSV string representing a vector * * @return a parsed vector */ public static BasicVector fromCSV(String csv) { return Vector.fromCSV(csv).to(Vectors.BASIC); } /** * Parses {@link BasicVector} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed vector */ public static BasicVector fromMatrixMarket(String mm) { return Vector.fromMatrixMarket(mm).to(Vectors.BASIC); } /** * Creates new {@link BasicVector} from * * @param list list containing doubles * * @return new vector from given double list */ public static BasicVector fromCollection(Collection list) { //TODO goto lambdas double[] self = new double[list.size()]; int i = 0; for (Number x : list) { self[i] = x.doubleValue(); i++; } return fromArray(self); } /** * Creates new {@link BasicVector} from index-value map * * @param map index-value map * * @param length vector length * * @return created vector */ public static BasicVector fromMap(Map map, int length) { return Vector.fromMap(map, length).to(Vectors.BASIC); } private double self[]; public BasicVector() { this(0); } public BasicVector(int length) { this(new double[length]); } public BasicVector(double array[]) { super(array.length); this.self = array; } @Override public double get(int i) { return self[i]; } @Override public void set(int i, double value) { self[i] = value; } @Override public void swapElements(int i, int j) { if (i != j) { double d = self[i]; self[i] = self[j]; self[j] = d; } } @Override public Vector copyOfLength(int length) { ensureLengthIsCorrect(length); double $self[] = new double[length]; System.arraycopy(self, 0, $self, 0, Math.min($self.length, self.length)); return new BasicVector($self); } @Override public double[] toArray() { double result[] = new double[length]; System.arraycopy(self, 0, result, 0, length); return result; } @Override public T to(VectorFactory factory) { if (factory.outputClass == BasicVector.class) { return factory.outputClass.cast(this); } return super.to(factory); } @Override public Vector blankOfLength(int length) { return BasicVector.zero(length); } @Override public byte[] toBinary() { int size = 1 + // 1 byte: class tag 4 + // 4 bytes: length (8 * length); // 8 * length bytes: values ByteBuffer buffer = ByteBuffer.allocate(size); buffer.put(VECTOR_TAG); buffer.putInt(length); for (double value: self) { buffer.putDouble(value); } return buffer.array(); } } la4j-0.6.0/src/main/java/org/la4j/vector/functor/000077500000000000000000000000001263320764000214115ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/vector/functor/VectorAccumulator.java000066400000000000000000000023301263320764000257140ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.functor; /** * A vector accumulator that accumulates vector's elements. */ public interface VectorAccumulator { /** * Updates a value that was accumulated so far with new * vector's element. * * @param i the element's index * @param value the element's value */ void update(int i, double value); /** * Returns the accumulated value and resets this accumulator. * * @return the accumulated value */ double accumulate(); } la4j-0.6.0/src/main/java/org/la4j/vector/functor/VectorFunction.java000066400000000000000000000021131263320764000252210ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.functor; /** * A vector function that takes a vector's element and produces a new value. */ public interface VectorFunction { /** * Evaluates vector's element. * * @param i the element's index * @param value the element's value * * @return a new element's value */ double evaluate(int i, double value); } la4j-0.6.0/src/main/java/org/la4j/vector/functor/VectorPredicate.java000066400000000000000000000020771263320764000253450ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.functor; /** * A vector predicate that tests vector's elements. */ public interface VectorPredicate { /** * Tests vector's element. * * @param i the element's index * @param value the element's value * * @return whether the element meets this predicate */ boolean test(int i, double value); } la4j-0.6.0/src/main/java/org/la4j/vector/functor/VectorProcedure.java000066400000000000000000000020021263320764000253610ustar00rootroot00000000000000/* * Copyright 2011-2014, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.functor; /** * A vector procedure that acts on vector's elements. */ public interface VectorProcedure { /** * Acts on vector's element. * * @param i the element's index * @param value the element's value */ void apply(int i, double value); } la4j-0.6.0/src/main/java/org/la4j/vector/sparse/000077500000000000000000000000001263320764000212265ustar00rootroot00000000000000la4j-0.6.0/src/main/java/org/la4j/vector/sparse/CompressedVector.java000066400000000000000000000450051263320764000253640ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Ewald Grusk * Yuriy Drozd * Maxim Samoylov * */ package org.la4j.vector.sparse; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.Random; import org.la4j.Vectors; import org.la4j.iterator.VectorIterator; import org.la4j.Vector; import org.la4j.vector.SparseVector; import org.la4j.vector.VectorFactory; import org.la4j.vector.functor.VectorFunction; import org.la4j.vector.functor.VectorProcedure; /** * A basic sparse vector implementation using underlying value and index arrays. * * A sparse data structure does not store blank elements, and instead just stores * elements with values. A sparse data structure can be initialized with a large * length but take up no storage until the space is filled with non-zero elements. * * However, there is a performance cost. Fetch/store operations take O(log n) * time instead of the O(1) time of a dense data structure. * * {@code CompressedVector} stores the underlying data in a two arrays: A values * array and a indices array. The values array matches the indices array, and * they're both sorted by the indices array. To get a value at an index, the * index is found in the indices array with a binary search and the respective * value is obtained from the values array. * */ public class CompressedVector extends SparseVector { private static final byte VECTOR_TAG = (byte) 0x10; private static final int MINIMUM_SIZE = 32; /** * Creates a zero {@link CompressedVector} of the given {@code length}. */ public static CompressedVector zero(int length) { return new CompressedVector(length); } /** * Creates a zero {@link CompressedVector} of the given {@code length} with * the given {@code capacity}. */ public static CompressedVector zero(int length, int capacity) { return new CompressedVector(length, capacity); } /** * Creates a random {@link CompressedVector} of the given {@code length} with * the given {@code density} and {@code Random}. */ public static CompressedVector random(int length, double density, Random random) { if (density < 0.0 || density > 1.0) { throw new IllegalArgumentException("The density value should be between 0 and 1.0"); } int cardinality = (int) (length * density); double values[] = new double[cardinality]; int indices[] = new int[cardinality]; for (int i = 0; i < cardinality; i++) { values[i] = random.nextDouble(); indices[i] = random.nextInt(length); } Arrays.sort(indices); return new CompressedVector(length, cardinality, values, indices); } /** * Creates a new {@link CompressedVector} from the given {@code array} with * compressing (copying) the underlying array. */ public static CompressedVector fromArray(double[] array) { int length = array.length; CompressedVector result = CompressedVector.zero(length); for (int i = 0; i < length; i++) { if (array[i] != 0.0) { result.set(i, array[i]); } } return result; } /** * Decodes {@link CompressedVector} from the given byte {@code array}. * * @param array the byte array representing a vector * * @return a decoded vector */ public static CompressedVector fromBinary(byte[] array) { ByteBuffer buffer = ByteBuffer.wrap(array); if (buffer.get() != VECTOR_TAG) { throw new IllegalArgumentException("Can not decode CompressedVector from the given byte array."); } int length = buffer.getInt(); int cardinality = buffer.getInt(); double[] values = new double[cardinality]; int[] indices = new int[cardinality]; for (int i = 0; i < cardinality; i++) { indices[i] = buffer.getInt(); values[i] = buffer.getDouble(); } return new CompressedVector(length, cardinality, values, indices); } /** * Parses {@link CompressedVector} from the given CSV string. * * @param csv the CSV string representing a vector * * @return a parsed vector */ public static CompressedVector fromCSV(String csv) { return Vector.fromCSV(csv).to(Vectors.COMPRESSED); } /** * Parses {@link CompressedVector} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed vector */ public static CompressedVector fromMatrixMarket(String mm) { return Vector.fromMatrixMarket(mm).to(Vectors.COMPRESSED); } /** * Creates new {@link CompressedVector} from collection * * @param list value list * * @return created vector */ public static CompressedVector fromCollection(Collection list) { return Vector.fromCollection(list).to(Vectors.COMPRESSED); } /** * Creates new {@link CompressedVector} from index-value map * * @param map index-value map * * @param length vector length * * @return created vector */ public static CompressedVector fromMap(Map map, int length) { //TODO goto lambdas int cardinality = map.size(); int[] indices = new int[cardinality]; double[] values = new double[cardinality]; int i = 0; for (Map.Entry entry : map.entrySet()) { int index = entry.getKey(); if (index < 0 || index >= length) { throw new IllegalArgumentException("Check your map: Index must be 0..n-1"); } indices[i] = index; values[i] = entry.getValue().doubleValue(); i++; } return new CompressedVector(length, cardinality, values, indices); } private double values[]; private int indices[]; public CompressedVector() { this(0); } public CompressedVector(int length) { this(length, 0); } public CompressedVector(int length, int capacity) { super(length); int alignedSize = align(length, capacity); this.values = new double[alignedSize]; this.indices = new int[alignedSize]; } public CompressedVector(int length, int cardinality, double values[], int indices[]) { super(length, cardinality); this.values = values; this.indices = indices; } @Override public double getOrElse(int i, double defaultValue) { ensureIndexIsInBounds(i); int k = searchForIndex(i); if (k < cardinality && indices[k] == i) { return values[k]; } return defaultValue; } @Override public void set(int i, double value) { ensureIndexIsInBounds(i); int k = searchForIndex(i); if (k < cardinality && indices[k] == i) { // if (Math.abs(value) > Vectors.EPS || value < 0.0) { if (value != 0.0) { values[k] = value; } else { remove(k); } } else { insert(k, i, value); } } @Override public void setAll(double value) { if (value == 0.0) { cardinality = 0; } else { if (values.length < length) { values = new double[length]; indices = new int[length]; } for (int i = 0; i < length; i++) { indices[i] = i; values[i] = value; } cardinality = length; } } @Override public void swapElements(int i, int j) { if (i == j) { return; } int ii = searchForIndex(i); int jj = searchForIndex(j); boolean iiNotZero = ii < cardinality && i == indices[ii]; boolean jjNotZero = jj < cardinality && j == indices[jj]; if (iiNotZero && jjNotZero) { double sd = values[ii]; values[ii] = values[jj]; values[jj] = sd; } else { double notZero = values[iiNotZero ? ii : jj]; int leftIndex = (ii < jj) ? ii : jj; int rightIndex = (ii > jj) ? ii : jj; if (((iiNotZero && (leftIndex == ii)) || (jjNotZero && (leftIndex == jj))) && (ii != jj)) { System.arraycopy(values, leftIndex + 1, values, leftIndex, cardinality - leftIndex); System.arraycopy(values, rightIndex - 1, values, rightIndex, cardinality - rightIndex); values[rightIndex - 1] = notZero; System.arraycopy(indices, leftIndex + 1, indices, leftIndex, cardinality - leftIndex); System.arraycopy(indices, rightIndex - 1, indices, rightIndex, cardinality - rightIndex); indices[rightIndex -1] = jjNotZero ? i : j; } else if((iiNotZero && (rightIndex == ii)) || (jjNotZero && (rightIndex == jj))) { System.arraycopy(values, rightIndex + 1, values, rightIndex, cardinality - rightIndex); System.arraycopy(values, leftIndex, values, leftIndex + 1, cardinality - leftIndex); values[leftIndex] = notZero; System.arraycopy(indices, rightIndex + 1, indices, rightIndex, cardinality - rightIndex); System.arraycopy(indices, leftIndex, indices, leftIndex + 1, cardinality - leftIndex); indices[leftIndex] = jjNotZero ? i : j; } } } @Override public Vector copyOfLength(int length) { ensureLengthIsCorrect(length); int $cardinality = (length >= this.length) ? cardinality : searchForIndex(length); int capacity = align(length, $cardinality); double $values[] = new double[capacity]; int $indices[] = new int[capacity]; System.arraycopy(values, 0, $values, 0, $cardinality); System.arraycopy(indices, 0, $indices, 0, $cardinality); return new CompressedVector(length, $cardinality, $values, $indices); } @Override public void each(VectorProcedure procedure) { int k = 0; for (int i = 0; i < length; i++) { if (k < cardinality && indices[k] == i) { procedure.apply(i, values[k++]); } else { procedure.apply(i, 0.0); } } } @Override public void eachNonZero(VectorProcedure procedure) { for (int i = 0; i < cardinality; i++) { procedure.apply(indices[i], values[i]); } } @Override public void updateAt(int i, VectorFunction function) { int k = searchForIndex(i); if (k < cardinality && indices[k] == i) { double value = function.evaluate(i, values[k]); // if (Math.abs(value) > Vectors.EPS || value < 0.0) { if (value != 0.0) { values[k] = value; } else { remove(k); } } else { insert(k, i, function.evaluate(i, 0.0)); } } @Override public boolean nonZeroAt(int i) { int k = searchForIndex(i); return k < cardinality && indices[k] == i; } @Override public T to(VectorFactory factory) { if (factory.outputClass == CompressedVector.class) { return factory.outputClass.cast(this); } return super.to(factory); } @Override public Vector blankOfLength(int length) { return CompressedVector.zero(length); } @Override public byte[] toBinary() { int size = 1 + // 1 byte: class tag 4 + // 4 bytes: length 4 + // 4 bytes: cardinality (8 * cardinality) + // 8 * cardinality bytes: values (8 * cardinality); // 8 * cardinality bytes: indices ByteBuffer buffer = ByteBuffer.allocate(size); buffer.put(VECTOR_TAG); buffer.putInt(length); buffer.putInt(cardinality); for (int i = 0; i < cardinality; i++) { buffer.putInt(indices[i]); buffer.putDouble(values[i]); } return buffer.array(); } /** * Does the binary searching to find the position in the value array given * it's index. * * @param i the index to search for * @return the position in the value array */ private int searchForIndex(int i) { if (cardinality == 0 || i > indices[cardinality - 1]) { return cardinality; } int left = 0; int right = cardinality; while (left < right) { int p = (left + right) / 2; if (indices[p] > i) { right = p; } else if (indices[p] < i) { left = p + 1; } else { return p; } } return left; } private void insert(int k, int i, double value) { // if (Math.abs(value) < Vectors.EPS && value >= 0.0) { if (value == 0.0) { return; } if (values.length < cardinality + 1) { growUp(); } if (cardinality - k > 0) { System.arraycopy(values, k, values, k + 1, cardinality - k); System.arraycopy(indices, k, indices, k + 1, cardinality - k); } // for (int kk = cardinality; kk > k; kk--) { // values[kk] = values[kk - 1]; // indices[kk] = indices[kk - 1]; // } values[k] = value; indices[k] = i; cardinality++; } private void remove(int k) { // TODO: https://github.com/vkostyukov/la4j/issues/87 cardinality--; if (cardinality - k > 0) { System.arraycopy(values, k + 1, values, k, cardinality - k); System.arraycopy(indices, k + 1, indices, k, cardinality - k); } // for (int kk = k; kk < cardinality; kk++) { // values[kk] = values[kk + 1]; // indices[kk] = indices[kk + 1]; // } } private void growUp() { if (values.length == length) { // This should never happen throw new IllegalStateException("This vector can't grow up."); } int capacity = Math.min(length, (cardinality * 3) / 2 + 1); double $values[] = new double[capacity]; int $indices[] = new int[capacity]; System.arraycopy(values, 0, $values, 0, cardinality); System.arraycopy(indices, 0, $indices, 0, cardinality); values = $values; indices = $indices; } private int align(int length, int capacity) { if (capacity < 0) { fail("Cardinality should be positive: " + capacity + "."); } if (capacity > length) { fail("Cardinality should be less then or equal to capacity: " + capacity + "."); } return Math.min(length, ((capacity / MINIMUM_SIZE) + 1) * MINIMUM_SIZE); } @Override public VectorIterator nonZeroIterator() { return new VectorIterator(length) { private boolean currentIsRemoved = false; private int k = -1; private int removedIndex = -1; @Override public int index() { return currentIsRemoved ? removedIndex : indices[k]; } @Override public double get() { return currentIsRemoved ? 0.0 : values[k]; } @Override public void set(double value) { if (value == 0.0 && !currentIsRemoved) { currentIsRemoved = true; removedIndex = indices[k]; CompressedVector.this.remove(k--); } else if (value != 0.0 && !currentIsRemoved) { values[k] = value; } else { currentIsRemoved = false; CompressedVector.this.insert(++k, removedIndex, value); } } @Override public boolean hasNext() { return k + 1 < cardinality; } @Override public Double next() { currentIsRemoved = false; return values[++k]; } }; } @Override public VectorIterator iterator() { return new VectorIterator(length) { private int k = 0; private int i = -1; private boolean currentNonZero = false; @Override public int index() { return i; } @Override public double get() { return currentNonZero ? values[k] : 0.0; } @Override public void set(double value) { if (currentNonZero) { if (value == 0.0) { CompressedVector.this.remove(k); currentNonZero = false; } else { values[k] = value; } } else { CompressedVector.this.insert(k, i, value); currentNonZero = true; } } @Override public boolean hasNext() { return i + 1 < length; } @Override public Double next() { if (currentNonZero) { k++; } i++; currentNonZero = k < cardinality && indices[k] == i; return get(); } }; } } la4j-0.6.0/src/test/000077500000000000000000000000001263320764000141205ustar00rootroot00000000000000la4j-0.6.0/src/test/java/000077500000000000000000000000001263320764000150415ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/000077500000000000000000000000001263320764000156305ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/000077500000000000000000000000001263320764000164625ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/M.java000066400000000000000000000011561263320764000175240ustar00rootroot00000000000000package org.la4j; import java.util.Arrays; public class M { public static double[] a(double... values) { return values; } public static Matrix m(double[]... values) { return Matrix.from2DArray(values); } public static Iterable ms(double[]... values) { return Arrays.asList( m(values).to(Matrices.CCS), m(values).to(Matrices.CRS), m(values).to(Matrices.BASIC_1D), m(values).to(Matrices.BASIC_2D) ); } public static Matrix mz(int rows, int columns) { return Matrix.zero(rows, columns); } } la4j-0.6.0/src/test/java/org/la4j/V.java000066400000000000000000000006721263320764000175370ustar00rootroot00000000000000package org.la4j; import java.util.Arrays; public final class V { public static Vector v(double... values) { return Vector.fromArray(values); } public static Iterable vs(double... values) { return Arrays.asList( v(values).to(Vectors.BASIC), v(values).to(Vectors.COMPRESSED) ); } public static Vector vz(int length) { return Vector.zero(length); } } la4j-0.6.0/src/test/java/org/la4j/decomposition/000077500000000000000000000000001263320764000213365ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/decomposition/AbstractDecompositorTest.java000066400000000000000000000027271263320764000272040ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.junit.Assert; import org.la4j.LinearAlgebra; import org.la4j.Matrix; import static org.la4j.M.*; public abstract class AbstractDecompositorTest { public abstract LinearAlgebra.DecompositorFactory decompositorFactory(); public void performTest(double[][] input, double[][][] output) { for (Matrix a: ms(input)) { MatrixDecompositor decompositor = a.withDecompositor(decompositorFactory()); Matrix[] decomposition = decompositor.decompose(); Assert.assertEquals(output.length, decomposition.length); for (int i = 0; i < decomposition.length; i++) { Assert.assertTrue(m(output[i]).equals(decomposition[i], 1e-3)); } } } } la4j-0.6.0/src/test/java/org/la4j/decomposition/CholeskyDecompositorTest.java000066400000000000000000000070021263320764000272110ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.junit.Test; import org.la4j.LinearAlgebra; public class CholeskyDecompositorTest extends AbstractDecompositorTest { @Override public LinearAlgebra.DecompositorFactory decompositorFactory() { return LinearAlgebra.CHOLESKY; } @Test public void testDecompose_1x1() { double[][] input = new double[][]{ {56} }; double[][][] output = new double[][][]{ { {7.483} } }; performTest(input, output); } @Test public void testDecompose_2x2() { double[][] input = new double[][]{ {1.0, -2.0}, {-2.0, 5.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0}, {-2.0, 1.0} } }; performTest(input, output); } @Test public void testDecompose_3x3() { double[][] input = new double[][]{ {1.0, -2.0, 0.0}, {-2.0, 5.0, 2.0}, {0.0, 2.0, 5.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0, 0.0}, {-2.0, 1.0, 0.0}, {0.0, 2.0, 1.0} } }; performTest(input, output); } @Test public void testDecompose_4x4() { double[][] input = new double[][]{ {18.0, 22.0, 54.0, 42.0}, {22.0, 70.0, 86.0, 62.0}, {54.0, 86.0, 174.0, 134.0}, {42.0, 62.0, 134.0, 106.0} }; double[][][] output = new double[][][]{ { {4.243, 0.000, 0.000, 0.000}, {5.185, 6.566, 0.000, 0.000}, {12.728, 3.046, 1.650, 0.000}, {9.899, 1.625, 1.850, 1.393} } }; performTest(input, output); } @Test public void testDecompose_5x5() { double[][] input = new double[][]{ {6.0, 15.0, 55.0, 72.0, 101.0}, {15.0, 55.0, 225.0, 229.0, 256.0}, {55.0, 225.0, 979.0, 1024.0, 1200.0}, {72.0, 229.0, 1024.0, 2048.0, 2057.0}, {101.0, 256.0, 1200.0, 2057.0, 6000.0} }; double[][][] output = new double[][][]{ { {2.449, 0.000, 0.000, 0.000, 0.000}, {6.124, 4.183, 0.000, 0.000, 0.000}, {22.454, 20.917, 6.110, 0.000, 0.000}, {29.394, 11.713, 19.476, 25.836, 0.000}, {41.233, 0.837, 42.007, 0.661, 50.340} } }; performTest(input, output); } } la4j-0.6.0/src/test/java/org/la4j/decomposition/EigenDecompositorTest.java000066400000000000000000000264311263320764000264660ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.junit.Test; import org.la4j.LinearAlgebra; public class EigenDecompositorTest extends AbstractDecompositorTest { @Override public LinearAlgebra.DecompositorFactory decompositorFactory() { return LinearAlgebra.EIGEN; } @Test public void testDecompose_1x1_symmetric_1() { double[][] input = new double[][]{ {76.0} }; double[][][] output = new double[][][]{ { {1.0} }, { {76.0} } }; performTest(input, output); } @Test public void testDecompose_1x1_symmetric_2() { double[][] input = new double[][]{ {-10.0} }; double[][][] output = new double[][][]{ { {1.0} }, { {-10.0} } }; performTest(input, output); } @Test public void testDecompose_2x2_symmetric_1() { double[][] input = new double[][]{ {-5.0, 12.0}, {12.0, 9.0} }; double[][][] output = new double[][][]{ { {0.867, 0.498}, {-0.498, 0.867} }, { {-11.892, 0.0}, {0.0, 15.892}, } }; performTest(input, output); } @Test public void testDecompose_2x2_symmetric_2() { double[][] input = new double[][]{ {25.0, 0}, {0.0, 9.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0}, {0.0, 1.0} }, { {25.0, 0.0}, {0.0, 9.0}, } }; performTest(input, output); } @Test public void testDecompose_3x3_symmetric_1() { double[][] input = new double[][]{ {1.5, 13.0, 9.4}, {13.0, 2.8, 3.6}, {9.4, 3.6, 4.4} }; double[][][] output = new double[][][]{ { {0.1199, -0.7559, 0.6435}, {0.5753, 0.5812, 0.5754}, {-0.8090, 0.3012, 0.5046} }, { {0.447, 0.0, 0.0}, {0.0, -12.242, 0.0}, {0.0, 0.0, 20.495} } }; performTest(input, output); } @Test public void testDecompose_3x3_symmetric_2() { double[][] input = new double[][]{ {1.0, 0.0, 0.0}, {0.0, 2.0, 0.0}, {0.0, 0.0, 4.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} }, { {1.0, 0.0, 0.0}, {0.0, 2.0, 0.0}, {0.0, 0.0, 4.0} } }; performTest(input, output); } @Test public void testDecompose_4x4_symmetric_1() { double[][] input = new double[][]{ {1.0, 5.0, 7.0, 9.0}, {5.0, 2.0, 8.0, 4.0}, {7.0, 8.0, 4.0, 1.0}, {9.0, 4.0, 1.0, 5.0} }; double[][][] output = new double[][][]{ { {0.537, -0.444, -0.192, -0.691}, {0.478, 0.788, 0.318, -0.223}, {0.502, -0.404, 0.590, 0.486}, {0.481, 0.135, -0.717, 0.486} }, { {20.058, 0.0, 0.0, 0.0}, {0.0, -4.237, 0.0, 0.0}, {0.0, 0.0, 4.814, 0.0}, {0.0, 0.0, 0.0, -8.635} } }; performTest(input, output); } @Test public void testDecompose_4x4_symmetric_2() { double[][] input = new double[][]{ {-8.0, 7.0, 2.0, -3.0}, {7.0, 20.0, -4.0, 5.0}, {2.0, -4.0, 4.0, 2.0}, {-3.0, 5.0, 2.0, -44.0} }; double[][][] output = new double[][][]{ { {-0.947, 0.203, -0.226, 0.1}, {0.227, 0.961, -0.13, -0.09}, {0.187, -0.179, -0.965, -0.052}, {0.127, 0.058, -0.04, 0.989} }, { {-9.672, 0.0, 0.0, 0.0}, {0.0, 22.525, 0.0, 0.0}, {0.0, 0.0, 4.013, 0.0}, {0.0, 0.0, 0.0, -44.866} } }; performTest(input, output); } @Test public void testDecompose_5x5_symmetric_1() { double[][] input = new double[][]{ {1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 2.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 3.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 4.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 5.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0} }, { {1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 2.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 3.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 4.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 5.0} } }; performTest(input, output); } @Test public void testDecompose_5x5_symmetric_2() { double[][] input = new double[][]{ {6.2, 4.7, 6.2, 45.9, 8.7}, {4.7, 12.6, 13.5, 0.6, 12.3}, {6.2, 13.5, 25.8, 1.2, 10.0}, {45.9, 0.6, 1.2, 34.1, 6.2}, {8.7, 12.3, 10.0, 6.2, 10.8} }; double[][][] output = new double[][][]{ { {-0.108, 0.035, 0.028, 0.580, -0.806}, {0.507, 0.708, -0.469, 0.141, 0.048}, {0.711, -0.108, 0.667, 0.186, 0.057}, {-0.296, 0.068, 0.068, 0.749, 0.585}, {0.372, -0.694, -0.574, 0.218, 0.057} }, { {39.207, 0.0, 0.0, 0.0, 0.0}, {0.0, -1.232, 0.0, 0.0, 0.0}, {0.0, 0.0, 8.082, 0.0, 0.0}, {0.0, 0.0, 0.0, 71.862, 0.0}, {0.0, 0.0, 0.0, 0.0, -28.420} } }; performTest(input, output); } @Test public void testDecompose_2x2_nonSymmetric_1() { double[][] input = new double[][]{ {1.0, 2.0}, {37.0, 24.0} }; double[][][] output = new double[][][]{ { {-0.573, -0.122}, {0.820, -1.572} }, { {-1.861, 0.0}, {0.0, 26.861} } }; performTest(input, output); } @Test public void testDecompose_2x2_nonSymmetric_2() { double[][] input = new double[][]{ {6.0, 99.0}, {-4.0, 12.0} }; double[][][] output = new double[][][]{ { {4.918, 0.750}, {0.000, 1.0} }, { {9.0, 19.672}, {-19.672, 9.0} } }; performTest(input, output); } @Test public void testDecompose_3x3_nonSymmetric() { double[][] input = new double[][]{ {16.0, -11.0, 99.0}, {7.0, -2.0, -42.0}, {8.0, -1.0, -7.0} }; double[][][] output = new double[][][]{ { {0.982, 0.644, -0.353}, {-0.026, -0.896, -2.320}, {0.187, -0.359, -0.186} }, { {35.149, 0.0, 0.0}, {0.0, -23.856, 0.0}, {0.0, 0.0, -4.293} } }; performTest(input, output); } @Test public void testDecompose_4x4_nonSymmetric() { double[][] input = new double[][]{ {-1.0, -4.0, 4.0, 8.0}, {4.0, 1.0, -8.0, 2.0}, {-2.0, -4.0, 5.0, 8.0}, {4.0, -1.0, -8.0, 4.0} }; double[][][] output = new double[][][]{ { {-0.497, -0.503, -2.828, -0.0}, {0.503, -0.497, 0.0, -2.828}, {-0.497, -0.503, -1.414, -0.0}, {0.503, -0.497, 0.0, -1.414} }, { {3.0, 4.0, 0.0, 0.0}, {-4.0, 3.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 2.0} } }; performTest(input, output); } @Test public void testDecompose_5x5_nonSymmetric() { double[][] input = new double[][]{ {26.0, -1.0, 2.0, 15.0, -3.0}, {-19.0, -11.0, 21.0, -4.0, 0.0}, {88.0, -22.0, -3.0, -5.0, -17.0}, {15.0, 45.0, 22.0, 42.0, 54.0}, {-17.0, 55.0, -9.0, 6.0, 2.0} }; double[][][] output = new double[][][]{ { {-0.109, 0.159, -0.525, -0.274, 0.091}, {-0.338, -0.250, -0.015, 0.244, 0.364}, {0.341, -0.082, -0.713, -0.389, 0.883}, {0.138, -0.492, -0.996, 0.032, -0.760}, {0.165, 0.840, 0.153, 0.457, -0.397} }, { {-23.664, 17.563, 0.0, 0.0, 0.0}, {-17.563, -23.664, 0.0, 0.0, 0.0}, {0.0, 0.0, 58.024, 0.0, 0.0}, {0.0, 0.0, 0.0, 22.652, 31.064}, {0.0, 0.0, 0.0, -31.064, 22.652} } }; performTest(input, output); } } la4j-0.6.0/src/test/java/org/la4j/decomposition/LUDecompositorTest.java000066400000000000000000000163711263320764000257610ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.junit.Test; import org.la4j.LinearAlgebra; public class LUDecompositorTest extends AbstractDecompositorTest { @Override public LinearAlgebra.DecompositorFactory decompositorFactory() { return LinearAlgebra.LU; } @Test public void testDecompose_1x1() { double[][] input = new double[][]{ {71.0} }; double[][][] output = new double[][][]{ { {1.0} }, { {71.0} }, { {1.0} } }; performTest(input, output); } @Test public void testDecompose_2x2() { double[][] input = new double[][]{ {14.0, 6.0}, {7.0, 18.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0}, {0.5, 1.0} }, { {14.0, 6.0}, {0.0, 15.0} }, { {1.0, 0.0}, {0.0, 1.0} } }; performTest(input, output); } @Test public void testDecompose_3x3() { double[][] input = new double[][]{ {1.0, 0.0, 2.0}, {0.0, 10.0, 0.0}, {2.0, 0.0, 9.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.5, 0.0, 1.0} }, { {2.0, 0.0, 9.0}, {0.0, 10.0, 0.0}, {0.0, 0.0, -2.5} }, { {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, } }; performTest(input, output); } @Test public void testDecompose_3x3_2() { double[][] input = new double[][]{ {77.0, 19.0, 1.0}, {-9.0, 17.0, 34.0}, {11.0, 100.0, -2.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0, 0.0}, {0.143, 1.0, 0.0}, {-0.117, 0.198, 1.0} }, { {77.0, 19.0, 1.0}, {0.0, 97.286, -2.143}, {0.0, 0.0, 34.540} }, { {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0} } }; performTest(input, output); } @Test public void testDecompose_4x4() { double[][] input = new double[][]{ {99.0, 1.0, -10.0, 6.0}, {14.0, 65.0, 7.0, 48.0}, {39.0, 40.0, -2.0, 9.0}, {11.0, 5.0, 43.0, 99.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0, 0.0, 0.0}, {0.141, 1.0, 0.0, 0.0}, {0.111, 0.075, 1.0, 0.0}, {0.394, 0.611, -0.074, 1.0} }, { {99.0, 1.0, -10.0, 6.0}, {0.0, 64.859, 8.414, 47.152}, {0.0, 0.0, 43.477, 94.779}, {0.0, 0.0, 0.000, -15.184} }, { {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 1.0, 0.0} } }; performTest(input, output); } @Test public void testDecompose_5x5() { double[][] input = new double[][]{ {6.0, 19.0, 81.0, 10.0, 65.0}, {100.0, 1.0, -10.0, 16.0, 71.0}, {58.0, -17.0, 88.0, 19.0, 29.0}, {-44.0, 4.0, 16.0, -100.0, 1.0}, {5.00, 76.0, 93.0, 35.0, -24.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0, 0.0, 0.0, 0.0}, {0.05, 1.0, 0.0, 0.0, 0.0}, {0.58, -0.231, 1.0, 0.0, 0.0}, {-0.44, 0.058, 0.053, 1.0, 0.0}, {0.06, 0.249, 0.505, 0.088, 1.0} }, { {100.0, 1.0, -10.0, 16.0, 71.0}, {0.0, 75.95, 93.5, 34.2, -27.55}, {0.0, 0.0, 115.442, 17.636, -18.557}, {0.0, 0.0, 0.0, -95.896, 34.837}, {0.0, 0.0, 0.0, 0.0, 73.930} }, { {0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0}, {1.0, 0.0, 0.0, 0.0, 0.0} } }; performTest(input, output); } @Test public void testDecompose_5x5_2() { double[][] input = new double[][]{ {88.0, 17.0, 6.0, 14.0, -1.0}, {5.0, -5.0, 41.0, 16.0, -29.0}, {7.0, -53.0, 19.0, 22.0, -99.0}, {3.0, 101.0, -91.0, 8.0, 26.0}, {71.0, -66.0, 46.0, 18.0, 23.0} }; double[][][] output = new double[][][]{ { {1.0, 0.0, 0.0, 0.0, 0.0}, {0.034, 1.0, 0.0, 0.0, 0.0}, {0.057, -0.059, 1.0, 0.0, 0.0}, {0.080, -0.541, -0.875, 1.0, 0.0}, {0.807, -0.794, -0.887, 0.687, 1.0} }, { {88.0, 17.0, 6.0, 14.0, -1.0}, {0.0, 100.42, -91.205, 7.523, 26.034}, {0.0, 0.0, 35.241, 15.651, -27.397}, {0.0, 0.0, 0.0, 38.656, -108.806}, {0.0, 0.0, 0.0, 0.0, 94.922} }, { {1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0} } }; performTest(input, output); } } la4j-0.6.0/src/test/java/org/la4j/decomposition/QRDecompositorTest.java000066400000000000000000000140271263320764000257570ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.junit.Test; import org.la4j.LinearAlgebra; public class QRDecompositorTest extends AbstractDecompositorTest { @Override public LinearAlgebra.DecompositorFactory decompositorFactory() { return LinearAlgebra.QR; } @Test public void testDecompose_1x1() { double[][] input = new double[][]{ {15.0} }; double[][][] output = new double[][][]{ { {-1.0} }, { {-15.0} } }; performTest(input, output); } @Test public void testDecompose_2x2() { double[][] input = new double[][]{ {5.0, 10.0}, {70.0, 11.0} }; double[][][] output = new double[][][]{ { {-0.071, 0.997}, {-0.997, -0.071} }, { {-70.178, -11.685}, {0.0, 9.191} } }; performTest(input, output); } @Test public void testDecompose_4x1() { double[][] input = new double[][]{ {8.0}, {2.0}, {-10.0}, {54.0} }; double[][][] output = new double[][][]{ { {-0.144}, {-0.036}, {0.180}, {-0.972} }, { {-55.534} } }; performTest(input, output); } @Test public void testDecompose_3x2() { double[][] input = new double[][]{ {65.0, 4.0}, {9.0, 12.0}, {32.0, 42.0} }; double[][][] output = new double[][][]{ { {-0.890, 0.455}, {-0.123, -0.246}, {-0.438, -0.856} }, { {-73.007, -23.450}, {0.000, -37.069} } }; performTest(input, output); } @Test public void testDecompose_3x3() { double[][] input = new double[][]{ {-8.0, 0.0, 0.0}, {0.0, -4.0, -6.0}, {0.0, 0.0, -2.0} }; double[][][] output = new double[][][]{ { {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0} }, { {8.0, 0.0, 0.0}, {0.0, 4.0, 6.0}, {0.0, 0.0, 2.0} } }; performTest(input, output); } @Test public void testDecompose_3x3_2() { double[][] input = new double[][]{ {-2.0, 6.0, 14.0}, {-10.0, -9.0, 6.0}, {12.0, 16.0, 100.0} }; double[][][] output = new double[][][]{ { {-0.127, 0.920, 0.371}, {-0.635, 0.212, -0.743}, {0.762, 0.330, -0.557} }, { {15.748, 17.145, 70.612}, {0.0, 8.891, 47.167}, {0.0, 0.0, -54.966} } }; performTest(input, output); } @Test public void testDecompose_4x3() { double[][] input = new double[][]{ {51.0, 4.0, 19.0}, {7.0, 17.0, 77.0}, {5.0, 6.0, 7.0}, {100.0, 1.0, -10.0} }; double[][][] output = new double[][][]{ { {-0.453, -0.121, 0.364}, {-0.062, -0.928, 0.236}, {-0.044, -0.323, -0.887}, {-0.888, 0.143, -0.158} }, { {-112.583, -4.024, -4.823}, {0.0, -18.050, -77.428}, {0.0, 0.0, 20.509} } }; performTest(input, output); } @Test public void testDecompose_5x5() { double[][] input = new double[][]{ {14.0, 66.0, 11.0, 4.0, 61.0}, {10.0, 22.0, 54.0, -1.0, 1.0}, {-19.0, 26.0, 4.0, 44.0, 14.0}, {87.0, -1.0, 34.0, 29.0, -2.0}, {18.0, 43.0, 51.0, 39.0, 16.0} }; double[][][] output = new double[][][]{ { {-0.151, -0.754, -0.520, 0.358, 0.097}, {-0.108, -0.242, 0.739, 0.388, 0.483}, {0.205, -0.342, -0.001, -0.771, 0.496}, {-0.941, 0.173, -0.088, -0.211, 0.180}, {-0.195, -0.475, 0.419, -0.287, -0.692} }, { {-92.466, -14.459, -48.602, -26.334, -7.700}, {0.0, -84.599, -41.067, -31.363, -58.992}, {0.0, 0.0, 52.549, 10.907, -24.128}, {0.0, 0.0, 0.0, -50.189, 7.268}, {0.0, 0.0, 0.0, 0.0, 1.908} } }; performTest(input, output); } } la4j-0.6.0/src/test/java/org/la4j/decomposition/SingularValueDecompositorTest.java000066400000000000000000000135021263320764000302130ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.decomposition; import org.junit.Test; import org.la4j.LinearAlgebra; public class SingularValueDecompositorTest extends AbstractDecompositorTest { @Override public LinearAlgebra.DecompositorFactory decompositorFactory() { return LinearAlgebra.SVD; } @Test public void testDecompose_1x1() { double[][] input = new double[][]{ {89.0} }; double[][][] output = new double[][][]{ { {1.0} }, { {89.0} }, { {1.0} } }; performTest(input, output); } @Test public void testDecompose_2x2() { double[][] input = new double[][]{ {7.0, 19.0}, {-1.0, 100.0} }; double[][][] output = new double[][][]{ { {0.187, -0.982}, {0.982, 0.187} }, { {101.790, 0.0}, {0.0, 7.064} }, { {0.003, -1.0}, {1.0, 0.003} } }; performTest(input, output); } @Test public void testDecompose_3x3() { double[][] input = new double[][]{ {2.0, 0.0, 0.0}, {0.0, 4.0, 0.0}, {0.0, 0.0, 8.0} }; double[][][] output = new double[][][]{ { {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {1.0, 0.0, 0.0} }, { {8.0, 0.0, 0.0}, {0.0, 4.0, 0.0}, {0.0, 0.0, 2.0} }, { {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {1.0, 0.0, 0.0} } }; performTest(input, output); } @Test public void testDecompose_3x1() { double[][] input = new double[][]{ {6.0}, {19.0}, {20.0} }; double[][][] output = new double[][][]{ { {-0.213}, {-0.673}, {-0.708} }, { {28.231} }, { {-1.0} } }; performTest(input, output); } @Test public void testDecompose_4x4() { double[][] input = new double[][]{ {9.0, 18.0, -1.0, 43.0}, {-9.0, 14.0, 85.0, -2.0}, {1.0, 100.0, 53.0, -22.0}, {28.0, 15.0, -28.0, 5.0} }; double[][][] output = new double[][][]{ { {-0.041, -0.261, 0.928, -0.262}, {-0.538, 0.664, 0.285, 0.434}, {-0.838, -0.467, -0.219, -0.179}, {0.087, -0.522, 0.095, 0.843} }, { {130.97, 0.0, 0.0, 0.0}, {0.0, 72.357, 0.0, 0.0}, {0.0, 0.0, 46.283, 0.0}, {0.0, 0.0, 0.0, 18.496} }, { {0.046, -0.323, 0.178, 0.928}, {-0.693, -0.691, 0.005, -0.207}, {-0.706, 0.643, 0.196, 0.222}, {0.139, -0.067, 0.964, -0.215} } }; performTest(input, output); } @Test public void testDecompose_5x5() { double[][] input = new double[][]{ {-1.0, 8.0, 17.0, 100.0, 10.0}, {4.0, -5.0, 44.0, 11.0, -66.0}, {22.0, 54.0, 24.0, -14.0, 1.0}, {99.0, 25.0, 77.0, -23.0, 4.0}, {11.0, 7.0, -15.0, -4.0, 81.0} }; double[][][] output = new double[][][]{ { {-0.072, 0.35, 0.927, 0.039, -0.105}, {0.252, 0.624, -0.132, -0.058, 0.725}, {0.337, -0.113, 0.036, 0.932, 0.06}, {0.901, -0.158, 0.124, -0.338, -0.182}, {-0.072, -0.671, 0.326, -0.110, 0.653} }, { {141.208, 0.0, 0.0, 0.0, 0.0}, {0.0, 112.592, 0.0, 0.0, 0.0}, {0.0, 0.0, 101.124, 0.0, 0.0}, {0.0, 0.0, 0.0, 44.635, 0.0}, {0.0, 0.0, 0.0, 0.0, 10.868} }, { {0.686, -0.207, 0.15, -0.324, -0.599}, {0.272, -0.134, 0.152, 0.934, -0.109}, {0.626, 0.254, 0.153, -0.087, 0.716}, {-0.210, 0.442, 0.856, -0.034, -0.161}, {-0.136, -0.824, 0.444, -0.115, 0.303} } }; performTest(input, output); } } la4j-0.6.0/src/test/java/org/la4j/inversion/000077500000000000000000000000001263320764000204765ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/inversion/AbstractInverterTest.java000066400000000000000000000067101263320764000254670ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.inversion; import org.junit.Assert; import org.junit.Test; import org.la4j.LinearAlgebra; import org.la4j.Matrix; import static org.la4j.M.*; import java.util.Random; public abstract class AbstractInverterTest { public abstract LinearAlgebra.InverterFactory inverterFactory(); protected void performTest(double input[][], LinearAlgebra.InverterFactory inverterFactory) { for (Matrix a: ms(input)) { MatrixInverter inverter = a.withInverter(inverterFactory); Matrix b = inverter.inverse(); // a * a^-1 = e Matrix c = a.multiply(b); Matrix e = Matrix.identity(a.rows()); Assert.assertTrue(e.equals(c, 1e-9)); } } @Test public void testInverse_1x1 () { double input[][] = new double[][] { { -0.5 } }; performTest(input, inverterFactory()); } @Test public void testInverse_2x2 () { double input[][] = new double[][] { { 1.0, 0.0 }, { 0.0, 1.0 } }; performTest(input, inverterFactory()); } @Test public void testInverse_4x4() { double input[][] = new double[][] { { 8.0, 16.0, -7.0, 10.0, 11.0 }, { 0.0, 1.0, 5.0, -4.0, 12.0 }, { 100.0, 2.0, 9.0, -17.0, 1.0 }, { -7.0, 2.0, 0.0, 11.0, 54.0 }, { -42.0, 1.0, 6.0, 52.0, 22.0 } }; performTest(input, inverterFactory()); } @Test public void testInverseInverse_5x5 () { double input[][] = new double[][] { { 12.0, 3.0, 478.0, 235.0, 2.0, 6.0 }, { 82.0, 1.0, 2.0, 835.0, 12.0, 11.0 }, { 1.0, -37.0, 13.0, 8.0, 237.0, 63.0 }, { 51.0, 84.0, 2.0, -35.0, 9.0, 2.0 }, { 29.0, -4.0, -27.0, -46.0, 29.0, 4.0 }, {-58.0, 939.0, 2.0, 59.0, 96.0, -5.0 } }; performTest(input, inverterFactory()); } @Test public void testInverseInverse_6x6 () { double input[][] = new double[][] { { 12.0, 3.0, 478.0, 235.0, 2.0, 6.0 }, { 82.0, 1.0, 2.0, 835.0, 12.0, 11.0 }, { 1.0, -37.0, 13.0, 8.0, 237.0, 63.0 }, { 51.0, 84.0, 2.0, -35.0, 9.0, 2.0 }, { 29.0, -4.0, -27.0, -46.0, 29.0, 4.0 }, {-58.0, 939.0, 2.0, 59.0, 96.0, -5.0 } }; performTest(input, inverterFactory()); } @Test public void testInverseRandom_100x100() { Random r = new Random(); double input[][] = new double[100][100]; for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { input[i][j] = r.nextDouble(); } } performTest(input, inverterFactory()); } } la4j-0.6.0/src/test/java/org/la4j/inversion/GaussJordanInverterTest.java000066400000000000000000000017231263320764000261430ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.inversion; import org.la4j.LinearAlgebra; public class GaussJordanInverterTest extends AbstractInverterTest { @Override public LinearAlgebra.InverterFactory inverterFactory() { return LinearAlgebra.GAUSS_JORDAN; } } la4j-0.6.0/src/test/java/org/la4j/inversion/NoPivotGaussInverterTest.java000066400000000000000000000017671263320764000263340ustar00rootroot00000000000000/* * Copyright 2011-2015, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.inversion; import org.la4j.LinearAlgebra; import org.la4j.LinearAlgebra.InverterFactory; public class NoPivotGaussInverterTest extends AbstractInverterTest { @Override public InverterFactory inverterFactory() { return LinearAlgebra.NO_PIVOT_GAUSS; } } la4j-0.6.0/src/test/java/org/la4j/linear/000077500000000000000000000000001263320764000177345ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/linear/AbstractSolverTest.java000066400000000000000000000026551263320764000244050ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.junit.Assert; import org.la4j.LinearAlgebra; import org.la4j.Matrix; import org.la4j.Vector; import static org.la4j.M.*; import static org.la4j.V.*; public abstract class AbstractSolverTest { public abstract LinearAlgebra.SolverFactory solverFactory(); public void performTest(double coefficientMatrix[][], double rightHandVector[]) { for (Matrix a: ms(coefficientMatrix)) { for (Vector b: vs(rightHandVector)) { LinearSystemSolver solver = a.withSolver(solverFactory()); Vector x = solver.solve(b); Vector ax = a.multiply(x); Assert.assertTrue(b.equals(ax, 1e-9)); } } } } la4j-0.6.0/src/test/java/org/la4j/linear/ForwardBackSubstitutionSolverTest.java000066400000000000000000000062571263320764000274660ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.junit.Test; import org.la4j.LinearAlgebra; public class ForwardBackSubstitutionSolverTest extends AbstractSolverTest { @Override public LinearAlgebra.SolverFactory solverFactory() { return LinearAlgebra.FORWARD_BACK_SUBSTITUTION; } @Test public void testSolve_1x1() { double a[][] = new double[][] { { 62.0 } }; double b[] = new double[] { -31.0 }; performTest(a, b); } @Test public void testSolve_2x2() { double a[][] = new double[][] { { 18.0, 4.0 }, { 10.0, -2.0 } }; double b[] = new double[] { 11.0, 4.0 }; performTest(a, b); } @Test public void testSolve_3x3() { double a[][] = new double[][] { { -19.0, 15.0, 4.0 }, { 2.0, -2.0, 1.0 }, { 9.0, 55.0, -1.0 } }; double b[] = new double[] { -146.0, 16.5, 7.5 }; performTest(a, b); } @Test public void testSolve_3x3_2() { double a[][] = new double[][] { { 1.0, 0.0, -10.0 }, { 20.0, 5.0, -1.0}, { 0.0, 0.0, -100.0 } }; double b[] = new double[] { 8.0, 115.2, 20.0 }; performTest(a, b); } @Test public void testSolve_4x4() { double a[][] = new double[][] { { 7.0, -42.0, 11.0, 2.0 }, { 8.0, 1.0, -2.0, -54.0 }, { 6.0, 0.0, 55.0, -15.0 }, { 24.0, -12.0, 44.0, -1.0 } }; double b[] = new double[] { 52.3, -32.6, -29.0, 37.1 }; performTest(a, b); } @Test public void testSolve_4x4_2() { double a[][] = new double[][] { { -100.0, 1.0, 0.0, -1.0 }, { 80.0, 6.0, -2.0, -6.0 }, { 0.0, -14.0, -110.0, 0.0 }, { 22.0, 0.0, 0.0, -16.0 } }; double b[] = new double[] { -41.5, 63.0, -1533.0, 155.0 }; performTest(a, b); } @Test public void testSolve_5x5() { double a[][] = new double[][] { { 4.0, 15.0, -0.5, 0.6, 0.0 }, { 9.0, 16.0, -9.0, 0.0, 1.0 }, { 77.0, -8.0, 16.0, -32.0, 0.0 }, { 8.0, -12.0, 22.0, -2.0, 4.0 }, { 0.0, 0.0, 9.0, -1.0, 60.0 } }; double b[] = new double[] { -110.44, -79.2, 862.8, 221.0, -3.1 }; performTest(a, b); } } la4j-0.6.0/src/test/java/org/la4j/linear/GaussianSolverTest.java000066400000000000000000000047061263320764000244130ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.junit.Ignore; import org.junit.Test; import org.la4j.LinearAlgebra; public class GaussianSolverTest extends AbstractSolverTest { @Override public LinearAlgebra.SolverFactory solverFactory() { return LinearAlgebra.GAUSSIAN; } @Test public void testSolve_1x1() { double a[][] = new double[][] { { 99.0 } }; double b[] = new double[] { -33.0 }; performTest(a, b); } @Test public void testSolve_2x2() { double a[][] = new double[][] { { 5.0, 10.0 }, { 15.0, -20.0 } }; double b[] = new double[] { 21.0, -37.0 }; performTest(a, b); } @Test public void testSolve_3x3() { double a[][] = new double[][] { { -8.0, 4.0, 2.0 }, { 10.0, 18.0, -70.0 }, { 3.0, -54.0, 19.0 } }; double b[] = new double[] { 7.0, -85.5, 0.5 }; performTest(a, b); } @Test public void testSolve_4x4() { double a[][] = new double[][] { { 9.0, 3.0, 0.0, 5.0 }, { 1.0, 0.0, 3.0, 6.0 }, { 7.0, 0.0, 2.0, 2.0 }, { 0.0, 3.0, 0.0, 0.0 } }; double b[] = new double[] { 0.0, 2.0, 0.0, 3.0 }; performTest(a, b); } @Test public void testSolve_5x5() { double a[][] = new double[][] { { 19.0, -1.0, 6.0, 18.0, -22.0 }, { 77.0, 4.0, 100.0, 16.0, 54.0 }, { -0.1, 19.0, 24.0, 3.0, 1.0 }, { 11.0, 8.0, 33.0, -10.0, 0.0 }, { -99.0, 7.0, 42.0, 42.0, 25.0 } }; double b[] = new double[] { 146.0, 486.0, 77.0, 282.0, -157.0 }; performTest(a, b); } } la4j-0.6.0/src/test/java/org/la4j/linear/JacobiSolverTest.java000066400000000000000000000053211263320764000240220ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.junit.Test; import org.la4j.LinearAlgebra; public class JacobiSolverTest extends AbstractSolverTest { @Override public LinearAlgebra.SolverFactory solverFactory() { return LinearAlgebra.JACOBI; } @Test public void testSolve_1x1() { double a[][] = new double[][] { { 144.0 } }; double b[] = new double[] { 12.0 }; performTest(a, b); } @Test public void testSolve_2x2() { double a[][] = new double[][] { { 66.0, 1.0 }, { 18.0, -20.0 } }; double b[] = new double[] { 257.0, 212.0 }; performTest(a, b); } @Test public void testSolve_3x3() { double a[][] = new double[][] { { 5.0, 0.0, 0.0 }, { 1.0, 7.0, 0.0 }, { 4.0, 0.0, 9.0 } }; double b[] = new double[] { 0.0, 2.0, 0.0 }; performTest(a, b); } @Test public void testSolve_3x3_2() { double a[][] = new double[][] { { 16.0, 1.0, -2.0 }, { 3.0, -5.0, 1.0 }, { 11.0, -2.0, 21.0 } }; double b[] = new double[] { 4.6, 3.3, -38.9 }; performTest(a, b); } @Test public void testSolve_4x4() { double a[][] = new double[][] { { 32.0, 4.0, 1.0, -3.0 }, { -2.0, -10.0, -6.0, 1.0 }, { 5.0, -2.0, -12.0, -1.0 }, { 0.0, -14.0, -6.0, 21.0 } }; double b[] = new double[] { -3.9, -5.4, 2.1, 18.4 }; performTest(a, b); } @Test public void testSolve_5x5() { double a[][] = new double[][] { { 10.0, 1.0, 0.0, -2.0, -3.0 }, { -1.0, -20.0, 0.0, 4.0, -3.0 }, { 2.0, -3.0, 30.0, 5.0, 0.0 }, { 5.0, 4.0, -1.0, 40.0, -6.0 }, { -2.0, 1.0, 4.0, 10.0, -50.0 } }; double b[] = new double[] { 0.07, -13.29, -12.45, -41.8, -32.8 }; performTest(a, b); } } la4j-0.6.0/src/test/java/org/la4j/linear/LeastSquaresSolverTest.java000066400000000000000000000103261263320764000252500ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.junit.Test; import org.la4j.LinearAlgebra; public class LeastSquaresSolverTest extends AbstractSolverTest { @Override public LinearAlgebra.SolverFactory solverFactory() { return LinearAlgebra.LEAST_SQUARES; } @Test public void testSolve_1x1() { double a[][] = new double[][] { { 55.0 } }; double b[] = new double[] { -5.0 }; performTest(a, b); } @Test public void testSolve_2x2() { double a[][] = new double[][] { { 6.0, 3.0 }, { 9.0, 18.0 } }; double b[] = new double[] { 5.0, 21.0 }; performTest(a, b); } @Test public void testSolve_2x1() { double a[][] = new double[][] { { 20.0 }, { -24.0 } }; double b[] = new double[] { -10.0, 12.0 }; performTest(a, b); } @Test public void testSolve_3x3() { double a[][] = new double[][] { { 99.0, -1.0, 0.0 }, { 9.0, 50.0, -2.0 }, { 10.0, 60.0, -4.0 } }; double b[] = new double[] { -98.9, -34.0, -56.0 }; performTest(a, b); } @Test public void testSolve_3x1() { double a[][] = new double[][] { { 44.0 }, { -4.0 }, { 444.0 } }; double b[] = new double[] { 4.4, -0.4, 44.4 }; performTest(a, b); } @Test public void testSolve_3x2() { double a[][] = new double[][] { { 10.0, 1.0 }, { 0.0, 2.0 }, { 4.0, -8.0 } }; double b[] = new double[] { 90.0, -20.0, 120.0 }; performTest(a, b); } @Test public void testSolve_4x4() { double a[][] = new double[][] { { 77.0, -5.0, 10.0, 0.0 }, { 44.0, 1.0, 0.0, -2.0 }, { 33.0, 20.0, 1.0, 0.0 }, { 0.0, 10.0, -12.0, 54.0 } }; double b[] = new double[] { 708.0, 405.0, 319.0, -230.0 }; performTest(a, b); } @Test public void testSolve_4x1() { double a[][] = new double[][] { { 2.0 }, { -16.0 }, { 32.0 }, { 8.0 } }; double b[] = new double[] { 1.0, -8.0, 16.0, 4.0 }; performTest(a, b); } @Test public void testSolve_4x2() { double a[][] = new double[][] { { 100.0, -88.0 }, { 40.0, -20.0 }, { -0.5, 0.5 }, { 1.0, 0.1 } }; double b[] = new double[] { -870.0, -196.0, 4.95, 1.1 }; performTest(a, b); } @Test public void testSolve_4x3() { double a[][] = new double[][] { { 64.0, -10.0, 1.0 }, { -0.6, 11.0, -15.0 }, { 29.0, 160.0, -9.0 }, { 11.0, -54.0, 22.0 } }; double b[] = new double[] { -36.5, 116.9, 1633.5, -540.0 }; performTest(a, b); } @Test public void testSolve_5x5() { double a[][] = new double[][] { { -5.0, 0.0, 1.0, 20.0, -16.0 }, { 0.0, -10.0, 2.0, -22.0, 14.0 }, { 0.0, -2.0, 0.5, 54.0, 17.0 }, { -0.2, 20.0, -10.0, 45.0, -1.0 }, { 8.0, 9.0, 11.0, -2.0, 15.0 } }; double b[] = new double[] { 42.5, -71.0, 117.75, 107.5, 41.0 }; performTest(a, b); } } la4j-0.6.0/src/test/java/org/la4j/linear/SeidelSolverTest.java000066400000000000000000000053211263320764000240400ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.junit.Test; import org.la4j.LinearAlgebra; public class SeidelSolverTest extends AbstractSolverTest { @Override public LinearAlgebra.SolverFactory solverFactory() { return LinearAlgebra.SEIDEL; } @Test public void testSolve_1x1() { double a[][] = new double[][] { { -77.0 } }; double b[] = new double[] { 11.0 }; performTest(a, b); } @Test public void testSolve_2x2() { double a[][] = new double[][] { { 10.0, 1.0 }, { 5.0, -22.0 } }; double b[] = new double[] { -20.0, -10.0 }; performTest(a, b); } @Test public void testSolve_3x3() { double a[][] = new double[][] { { 5.0, 0.0, 0.0 }, { 1.0, 7.0, 0.0 }, { 4.0, 0.0, 9.0 } }; double b[] = new double[] { 0.0, 2.0, 0.0 }; performTest(a, b); } @Test public void testSolve_3x3_2() { double a[][] = new double[][] { { 10.0, 1.0, -2.0 }, { 3.0, -8.0, 1.0 }, { 11.0, -2.0, 15.0 } }; double b[] = new double[] { 6.8, -10.1, -36.9 }; performTest(a, b); } @Test public void testSolve_4x4() { double a[][] = new double[][] { { 32.0, 4.0, 1.0, -3.0 }, { -2.0, -10.0, -6.0, 1.0 }, { 5.0, -2.0, -12.0, -1.0 }, { 0.0, -14.0, -6.0, 21.0 } }; double b[] = new double[] { -3.9, -5.4, 2.1, 18.4 }; performTest(a, b); } @Test public void testSolve_5x5() { double a[][] = new double[][] { { 10.0, 1.0, 0.0, -2.0, -3.0 }, { -1.0, -20.0, 0.0, 4.0, -3.0 }, { 2.0, -3.0, 30.0, 5.0, 0.0 }, { 5.0, 4.0, -1.0, 40.0, -6.0 }, { -2.0, 1.0, 4.0, 10.0, -50.0 } }; double b[] = new double[] { 0.07, -13.29, -12.45, -41.8, -32.8 }; performTest(a, b); } } la4j-0.6.0/src/test/java/org/la4j/linear/SquareRootSolverTest.java000066400000000000000000000053501263320764000247410ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.junit.Test; import org.la4j.LinearAlgebra; public class SquareRootSolverTest extends AbstractSolverTest { @Override public LinearAlgebra.SolverFactory solverFactory() { return LinearAlgebra.SQUARE_ROOT; } @Test public void testSolve_1x1() { double a[][] = new double[][] { { 44.0 } }; double b[] = new double[] { -22.0 }; performTest(a, b); } @Test public void testSolve_2x2() { double a[][] = new double[][] { { -7.0, 77.0 }, { 77.0, 14.0 } }; double b[] = new double[] { -77.0, 768.6 }; performTest(a, b); } @Test public void testSolve_3x3() { double a[][] = new double[][] { { 1.0, 0.0, 0.0 }, { 0.0, 5.0, 0.0 }, { 0.0, 0.0, 9.0 } }; double b[] = new double[] { 0.0, 2.0, 0.0 }; performTest(a, b); } @Test public void testSolve_3x3_2() { double a[][] = new double[][] { { 9.0, -1.0, -18.0 }, { -1.0, 6.0, -3.0 }, { -18.0, -3.0, 33.0 } }; double b[] = new double[] { -45.0, -10.0, 81.0 }; performTest(a, b); } @Test public void testSolve_4x4() { double a[][] = new double[][] { { -55.0, 11.0, 1.0, 0.0 }, { 11.0, 66.0, 4.0, -1.0 }, { 1.0, 4.0, -44.0, -9.0 }, { 0.0, -1.0, -9.0, 33.0 } }; double b[] = new double[] { -276.0, 29.0, -439.0, -89.0 }; performTest(a, b); } @Test public void testSolve_5x5() { double a[][] = new double[][] { { 14.0, 0.0, -10.0, 11.0, -4.0 }, { 0.0, 21.0, -2.0, 0.0, 11.0 }, { -10.0, -2.0, -7.0, 1.0, -3.0 }, { 11.0, 0.0, 1.0, -28.0, 6.0 }, { -4.0, 11.0, -3.0, 6.0, 0.7 }, }; double b[] = new double[] { 104.0, -256.0, -45.0, 54.0, -143.8 }; performTest(a, b); } } la4j-0.6.0/src/test/java/org/la4j/linear/SweepSolverTest.java000066400000000000000000000044331263320764000237210ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.linear; import org.junit.Test; import org.la4j.LinearAlgebra; public class SweepSolverTest extends AbstractSolverTest { @Override public LinearAlgebra.SolverFactory solverFactory() { return LinearAlgebra.SWEEP; } @Test public void testSolve_3x3() { double a[][] = new double[][] { { 5.0, 1.0, 0.0 }, { 1.0, 7.0, 3.0 }, { 0.0, 2.0, 9.0 } }; double b[] = new double[] { 0.0, 2.0, 0.0 }; performTest(a, b); } @Test public void testSolve_3x3_2() { double a[][] = new double[][] { { -6.0, 11.0, 0.0 }, { 17.0, 18.0, -20.0 }, { 0.0, 20.0, -9.0 } }; double b[] = new double[] { -356.0, 497.0, -209.0 }; performTest(a, b); } @Test public void testSolve_4x4() { double a[][] = new double[][] { { 1.0, 18.0, 0.0, 0.0 }, { -21.0, 2.0, -53.0, 0.0 }, { 0.0, 19.0, 3.0, -6.0 }, { 0.0, 0.0, 66.0, -4.0 } }; double b[] = new double[] { -180.0, -394.7, -215.3, -10.6 }; performTest(a, b); } @Test public void testSolve_5x5() { double a[][] = new double[][] { { 7.0, 8.0, 0.0, 0.0, 0.0 }, { -9.0, 100.0, -1.0, 0.0, 0.0 }, { 0.0, 2.0, 3.0, 10.0, 0.0 }, { 0.0, 0.0, -1.0, -77.0, 11.0 }, { 0.0, 0.0, 0.0, 5.0, -2.0 } }; double b[] = new double[] { -1.0, -111.0, -16.0, 185.0, -16.0 }; performTest(a, b); } } la4j-0.6.0/src/test/java/org/la4j/matrix/000077500000000000000000000000001263320764000177665ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/matrix/MatrixTest.java000066400000000000000000001620571263320764000227500ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Evgenia Krivova * Jakob Moellers * Maxim Samoylov * Anveshi Charuvaka * Todd Brunhoff * Catherine da Graca * */ package org.la4j.matrix; import java.util.ArrayList; import org.junit.Assert; import org.junit.Test; import org.la4j.*; import org.la4j.vector.DenseVector; import static org.la4j.M.*; import static org.la4j.V.*; public abstract class MatrixTest { protected MatrixFactory factory; public MatrixTest(MatrixFactory factory) { this.factory = factory; } public T m(double[]... values) { return M.m(values).to(factory); } public T mz(int rows, int columns) { return M.mz(rows, columns).to(factory); } @Test public void testInsert_3x3_into_3x3() { Matrix a = m(a(1.0, 2.0, 3.0), a(4.0, 5.0, 6.0), a(7.0, 8.0, 9.0)); Matrix b = mz(3, 3); Assert.assertEquals(a, b.insert(a)); } @Test public void testInsert_2x2_into_3x3() { Matrix a = m(a(1.0, 2.0), a(3.0, 4.0)); Matrix b = mz(3, 3); Assert.assertEquals(a, b.insert(a).slice(0, 0, 2, 2)); } @Test public void testInsert_2x2_into_3x3_partial() { Matrix a = m(a(1.0, 2.0), a(3.0, 4.0)); Matrix b = mz(3, 3); Assert.assertEquals(a.slice(0, 0, 1, 2), b.insert(a, 1, 2).slice(0, 0, 1, 2)); } @Test public void testInsert_3x3_slice_into_4x4_offset() { Matrix a = m(a(1.0, 2.0, 3.0), a(4.0, 5.0, 6.0), a(7.0, 8.0, 9.0)); Matrix b = mz(4, 4); Assert.assertEquals(a.slice(1, 1, 3, 3), b.insert(a, 1, 1, 1, 1, 2, 2).slice(1, 1, 3, 3)); } @Test public void testInsert_2x2_into_4x4_offset() { Matrix a = m(a(1.0, 2.0), a(3.0, 4.0)); Matrix b = mz(3, 3); Assert.assertEquals(a, b.insert(a, 1, 1, a.rows(), a.columns()).slice(1, 1, 3, 3)); } @Test public void testInsert_3x1_into_3x3_offset() { Matrix a = m(a(1.0), a(2.0), a(3.0)); Matrix b = mz(3, 3); Assert.assertEquals(a, b.insert(a, 0, 2, a.rows(), a.columns()).slice(0, 2, 3, 3)); } @Test public void testInsert_1x3_into_3x3_offset() { Matrix a = m(a(1.0, 2.0, 3.0)); Matrix b = mz(3, 3); Assert.assertEquals(a, b.insert(a, 2, 0, a.rows(), a.columns()).slice(2, 0, 3, 3)); } @Test public void testAccess_3x3() { Matrix a = m(a(1.0, 0.0, 3.0), a(0.0, 5.0, 0.0), a(7.0, 0.0, 9.0)); a.set(0, 1, a.get(1, 1) * 2); Assert.assertEquals(10.0, a.get(0, 1), Matrices.EPS); } @Test public void testGetColumn_4x4() { Matrix a = m(a(8.0, 3.0, 1.0, 9.0), a(4.0, 9.0, 6.0, 6.0), a(9.0, 1.0, 1.0, 4.0), a(5.0, 7.0, 3.0, 0.0)); Vector b = v(8.0, 4.0, 9.0, 5.0); Vector c = v(1.0, 6.0, 1.0, 3.0); Assert.assertEquals(b, a.getColumn(0)); Assert.assertEquals(c, a.getColumn(2)); } @Test public void testGetRow_4x4() { Matrix a = m(a(8.0, 3.0, 1.0, 9.0), a(4.0, 9.0, 6.0, 6.0), a(9.0, 1.0, 1.0, 4.0), a(5.0, 7.0, 3.0, 0.0)); Vector b = v(8.0, 3.0, 1.0, 9.0); Vector c = v(9.0, 1.0, 1.0, 4.0); Assert.assertEquals(b, a.getRow(0)); Assert.assertEquals(c, a.getRow(2)); } @Test public void testResize_3x3_to_4x4_to_2x2() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Matrix b = m(a(1.0, 0.0, 0.0, 0.0), a(0.0, 5.0, 0.0, 0.0), a(0.0, 0.0, 9.0, 0.0), a(0.0, 0.0, 0.0, 0.0)); Matrix c = m(a(1.0, 0.0), a(0.0, 5.0)); a = a.copyOfShape(a.rows() + 1, a.columns() + 1); Assert.assertEquals(b, a); a = a.copyOfShape(a.rows() - 2, a.columns() - 2); Assert.assertEquals(c, a); } @Test public void testResize_2x3_to_3x4_to_1x2() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0)); Matrix b = m(a(1.0, 0.0, 0.0, 0.0), a(0.0, 5.0, 0.0, 0.0), a(0.0, 0.0, 0.0, 0.0)); Matrix c = m(a(1.0, 0.0)); a = a.copyOfShape(a.rows() + 1, a.columns() + 1); Assert.assertEquals(b, a); a = a.copyOfShape(a.rows() - 2, a.columns() - 2); Assert.assertEquals(c, a); } @Test public void testResize_2x3_to_2x4_to_2x1() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0)); Matrix b = m(a(1.0, 0.0, 0.0, 0.0), a(0.0, 5.0, 0.0, 0.0)); Matrix c = m(a(1.0), a(0.0)); a = a.copyOfShape(a.rows(), a.columns() + 1); Assert.assertEquals(b, a); a = a.copyOfShape(a.rows(), a.columns() - 3); Assert.assertEquals(c, a); } @Test public void testResize_3x5_to_4x5_to_2x5() { Matrix a = m(a(1.0, 0.0, 0.0, 0.0, 0.0), a(0.0, 5.0, 0.0, 0.0, 0.0), a(0.0, 0.0, 7.0, 0.0, 0.0)); Matrix b = m(a(1.0, 0.0, 0.0, 0.0, 0.0), a(0.0, 5.0, 0.0, 0.0, 0.0), a(0.0, 0.0, 7.0, 0.0, 0.0), a(0.0, 0.0, 0.0, 0.0, 0.0)); Matrix c = m(a(1.0, 0.0, 0.0, 0.0, 0.0), a(0.0, 5.0, 0.0, 0.0, 0.0)); a = a.copyOfShape(a.rows() + 1, a.columns()); Assert.assertEquals(b, a); a = a.copyOfShape(a.rows() - 2, a.columns()); Assert.assertEquals(c, a); } @Test public void testSlice_4x4_to_2x2() { Matrix a = m(a(1.0, 0.0, 0.0, 0.0), a(0.0, 5.0, 0.0, 0.0), a(0.0, 0.0, 9.0, 0.0), a(0.0, 0.0, 0.0, 15.0)); Matrix b = m(a(5.0, 0.0), a(0.0, 9.0)); Assert.assertEquals(b, a.slice(1, 1, 3, 3)); } @Test public void testSlice_3x4_to_1x4() { Matrix a = m(a(1.0, 0.0, 3.0, 0.0), a(0.0, 5.0, 0.0, 7.0), a(4.0, 0.0, 9.0, 0.0)); Matrix b = m(a(4.0, 0.0, 9.0, 0.0)); Assert.assertEquals(b, a.slice(2, 0, 3, 4)); } @Test public void testSwap_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Matrix b = m(a(0.0, 0.0, 9.0), a(0.0, 5.0, 0.0), a(1.0, 0.0, 0.0)); Matrix c = m(a(9.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 1.0)); a.swapRows(0, 2); Assert.assertEquals(b, a); b.swapColumns(0, 2); Assert.assertEquals(c, b); } @Test public void testSwap_2x4() { Matrix a = m(a(1.0, 0.0, 0.0, 3.0), a(0.0, 5.0, 4.0, 0.0)); Matrix b = m(a(0.0, 5.0, 4.0, 0.0), a(1.0, 0.0, 0.0, 3.0)); Matrix c = m(a(0.0, 4.0, 5.0, 0.0), a(1.0, 0.0, 0.0, 3.0)); a.swapRows(0, 1); Assert.assertEquals(b, a); b.swapColumns(1, 2); Assert.assertEquals(c, b); } @Test public void testSwap_5x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 4.0), a(7.0, 0.0, 2.0), a(0.0, 8.0, 0.0), a(5.0, 0.0, 6.0)); Matrix b = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 4.0), a(0.0, 8.0, 0.0), a(7.0, 0.0, 2.0), a(5.0, 0.0, 6.0)); Matrix c = m(a(1.0, 0.0, 0.0), a(0.0, 4.0, 5.0), a(0.0, 0.0, 8.0), a(7.0, 2.0, 0.0), a(5.0, 6.0, 0.0)); a.swapRows(2, 3); Assert.assertEquals(b, a); b.swapColumns(1, 2); Assert.assertEquals(c, b); } @Test public void testTranspose_4x4() { Matrix a = m(a(0.0, 14.2, 0.0, 4.0), a(0.0, 5.0, 10.0, 0.0), a(0.0, 3.0, 0.0, 2.3), a(11.0, 7.0, 0.0, 1.0)); Matrix b = m(a(0.0, 0.0, 0.0, 11.0), a(14.2, 5.0, 3.0, 7.0), a(0.0, 10.0, 0.0, 0.0), a(4.0, 0.0, 2.3, 1.0)); Matrix c = a.transpose(); Assert.assertEquals(b, c); Matrix d = c.transpose(); Assert.assertEquals(a, d); } @Test public void testTranspose_5x3() { Matrix a = m(a(0.0, 14.2, 0.0), a(0.0, 5.0, 10.0), a(0.0, 3.0, 0.0), a(11.0, 7.0, 0.0), a(12.0, 7.5, 0.0)); Matrix b = m(a(0.0, 0.0, 0.0, 11.0, 12.0), a(14.2, 5.0, 3.0, 7.0, 7.5), a(0.0, 10.0, 0.0, 0.0, 0)); Matrix c = a.transpose(); Assert.assertEquals(b, c); Matrix d = c.transpose(); Assert.assertEquals(a, d); } @Test public void testTranspose_6x5() { Matrix a = m(a(8.93, 3.96, 7.37, 3.43, 7.05), a(5.88, 8.26, 5.79, 9.08, 7.75), a(6.57, 2.51, 8.8, 1.16, 8.11), a(9.3, 9.61, 0.87, 2.3, 2.93), a(3.65, 4.63, 7.83, 3.66, 9.04), a(0.08, 6.12, 6.15, 4.93, 6.72)); Matrix b = m(a(8.93, 5.88, 6.57, 9.3, 3.65, 0.08), a(3.96, 8.26, 2.51, 9.61, 4.63, 6.12), a(7.37, 5.79, 8.8, 0.87, 7.83, 6.15), a(3.43, 9.08, 1.16, 2.3, 3.66, 4.93), a(7.05, 7.75, 8.11, 2.93, 9.04, 6.72)); Matrix c = a.transpose(); Assert.assertEquals(b, c); Matrix d = c.transpose(); Assert.assertEquals(a, d); } @Test public void testAdd_3x3() { for (Matrix b: ms(a(11.0, 10.0, 10.0), a(10.0, 15.0, 10.0), a(10.0, 10.0, 19.0))) { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Matrix c = m(a(12.0, 10.0, 10.0), a(10.0, 20.0, 10.0), a(10.0, 10.0, 28.0)); Assert.assertEquals(b, a.add(10.0)); Assert.assertEquals(c, a.add(b)); } } @Test public void testAdd_4x2() { for (Matrix b: ms(a(11.0, 10.0), a(10.0, 15.0), a(17.0, 10.0), a(10.0, 19.0))) { Matrix a = m(a(1.0, 0.0), a(0.0, 5.0), a(7.0, 0.0), a(0.0, 9.0)); Matrix c = m(a(12.0, 10.0), a(10.0, 20.0), a(24.0, 10.0), a(10.0, 28.0)); Assert.assertEquals(b, a.add(10.0)); Assert.assertEquals(c, a.add(b)); } } @Test public void testSubtract_3x3() { for (Matrix b: ms(a(-9.0, -10.0, -10.0), a(-10.0, -5.0, -10.0), a(-10.0, -10.0, -1.0))) { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Matrix c = m(a(10.0, 10.0, 10.0), a(10.0, 10.0, 10.0), a(10.0, 10.0, 10.0)); Assert.assertEquals(b, a.subtract(10.0)); Assert.assertEquals(c, a.subtract(b)); } } @Test public void testSubtract_2x4() { for (Matrix b: ms(a(-9.0, -10.0, -3.0, -10.0), a(-10.0, -5.0, -10.0, -1.0))) { Matrix a = m(a(1.0, 0.0, 7.0, 0.0), a(0.0, 5.0, 0.0, 9.0)); Matrix c = m(a(10.0, 10.0, 10.0, 10.0), a(10.0, 10.0, 10.0, 10.0)); Assert.assertEquals(b, a.subtract(10.0)); Assert.assertEquals(c, a.subtract(b)); } } @Test public void testMultiply_2x3() { Matrix a = m(a(1.0, 0.0, 3.0), a(0.0, 5.0, 0.0)); Matrix b = m(a(2.0, 0.0, 6.0), a(0.0, 10.0, 0.0)); Assert.assertEquals(b, a.multiply(2.0)); } @Test public void testMultiply_2x3_3() { for (Vector b: vs(10.0, 0.0, 30.0)) { Matrix a = m(a(1.0, 0.0, 3.0), a(0.0, 5.0, 0.0)); Vector c = v(100.0, 0.0); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_5x2_2() { for (Vector b: vs(0.0, 10.0)) { Matrix a = m(a(1.0, 0.0), a(0.0, 5.0), a(7.0, 0.0), a(3.0, 0.0), a(0.0, 1.0)); Vector c = v(0.0, 50.0, 0.0, 0.0, 10.0); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_1x1_1x1() { for (Matrix b: ms(a(8.48))) { Matrix a = m(a(3.37)); Matrix c = m(a(28.5776)); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_2x2_2x2() { for (Matrix b: ms(a(3.85, 8.28), a(8.02, 8.39))) { Matrix a = m(a(2.46, 1.68), a(7.57, 2.47)); Matrix c = m(a(22.9446, 34.464), a(48.9539, 83.4029)); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_4x4_4x4() { for (Matrix b: ms(a(4.0, 9.0, 0.0, 3.0), a(6.0, 7.0, 7.0, 6.0), a(9.0, 4.0, 3.0, 3.0), a(4.0, 4.0, 1.0, 6.0))) { Matrix a = m(a(8.0, 3.0, 1.0, 9.0), a(4.0, 9.0, 6.0, 6.0), a(9.0, 1.0, 1.0, 4.0), a(5.0, 7.0, 3.0, 0.0)); Matrix c = m(a(95.0, 133.0, 33.0, 99.0), a(148.0, 147.0, 87.0, 120.0), a(67.0, 108.0, 14.0, 60.0), a(89.0, 106.0, 58.0, 66.0)); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_4x1_1x4() { for (Matrix b: ms(a(5.19, 6.06, 6.12, 5.92))) { Matrix a = m(a(6.31), a(6.06), a(4.94), a(9.62)); Matrix c = m(a(32.7489, 38.2386, 38.6172, 37.3552), a(31.4514, 36.7236, 37.0872, 35.8752), a(25.6386, 29.9364, 30.2328, 29.2448), a(49.9278, 58.2972, 58.8744, 56.9504)); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_1x10_10x1() { for (Matrix b: ms(a(9.81), a(0.14), a(8.91), a(8.54), a(0.97), a(2.55), a(1.11), a(2.52), a(7.71), a(1.69))) { Matrix a = m(a(0.28, 1.61, 5.11, 1.71, 2.21, 5.97, 2.61, 2.58, 0.07, 3.78)); Matrix c = m(a(96.7995)); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_3x2_2x3() { for (Matrix b: ms(a(0.0, 3.0, 0.0), a(2.0, 0.0, 4.0))) { Matrix a = m(a(1.0, 9.0), a(9.0, 1.0), a(8.0, 9.0)); Matrix c = m(a(18.0, 3.0, 36.0), a(2.0, 27.0, 4.0), a(18.0, 24.0, 36.0)); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_4x9_9x4() { for (Matrix b: ms(a(9.28, 7.63, 4.1, 4.71), a(4.68, 2.82, 9.18, 5.39), a(4.54, 6.86, 1.29, 5.4), a(8.72, 2.06, 4.28, 7.37), a(2.43, 3.7, 7.52, 5.87), a(8.21, 9.36, 4.85, 0.3), a(9.87, 8.19, 5.03, 6.14), a(9.47, 4.28, 3.86, 3.12), a(5.29, 4.41, 5.23, 4.85))) { Matrix a = m(a(5.98, 3.76, 9.01, 9.68, 2.12, 6.34, 0.64, 6.22, 1.16), a(8.4, 9.65, 7.06, 2.56, 7.66, 4.69, 3.29, 8.6, 8.55), a(4.99, 7.06, 6.07, 7.53, 0.08, 1.08, 9.69, 8.51, 6.61), a(4.72, 7.06, 4.0, 0.75, 2.45, 4.4, 8.33, 5.81, 0.57)); Matrix c = m(a(326.9658, 242.1452, 192.0747, 211.7362), a(393.7521, 318.7092, 317.9021, 283.44), a(392.8255, 270.4737, 247.3277, 268.7303), a(283.873, 230.76, 199.6044, 175.1515)); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiplyByItsTranspose_2x2() { Matrix a = m(a(1.0, 2.0), a(0.0, 1.0)); Matrix b = m(a(5.0, 2.0), a(2.0, 1.0)); Assert.assertEquals(a.multiplyByItsTranspose(), b); } @Test public void testMultiplyByItsTranspose_4x4() { Matrix a = m(a(3.0, 6.0, 7.0, 11.0), a(5.0, 2.0, 4.0, 7.0), a(1.0, -6.0, 2.0, 9.0), a(10.0, -3.0, -7.0, 9.0)); Matrix b = m(a(215.0, 132.0, 80.0, 62.0), a(132.0, 94.0, 64.0, 79.0), a(80.0, 64.0, 122.0, 95.0), a(62.0, 79.0, 95.0, 239.0)); Assert.assertEquals(a.multiplyByItsTranspose(), b); } @Test public void testMultiplyByItsTranspose_2x3() { Matrix a = m(a(1.0, 2.0, 3.0), a(0.0, 1.0, 2.0)); Assert.assertEquals(a.multiplyByItsTranspose(), a.multiply(a.transpose())); } @Test public void testMultiplyByItsTranspose_5x3() { Matrix a = m(a(0.0, 2.0, 0.0), a(0.0, 1.0, 2.0), a(4.0, 0.0, 0.0), a(0.0, 5.0, 7.0), a(1.0, 1.0, 0.0)); Assert.assertEquals(a.multiplyByItsTranspose(), a.multiply(a.transpose())); } @Test public void testDivide_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Matrix b = m(a(0.1, 0.0, 0.0), a(0.0, 0.5, 0.0), a(0.0, 0.0, 0.9)); Assert.assertEquals(b, a.divide(10.0)); } @Test public void testKronecker_3x3_2x2() { for (Matrix b: ms(a(10.0, 0.0), a(0.0, 20.0))) { Matrix a = m(a(1.0, 0.0, 3.0), a(0.0, 5.0, 0.0)); Matrix c = m(a(10.0, 0.0, 0.0, 0.0, 30.0, 0.0), a(0.0, 20.0, 0.0, 0.0, 0.0, 60.0), a(0.0, 0.0, 50.0, 0.0, 0.0, 0.0), a(00.0, 0.0, 0.0, 100.0, 0.0, 0.0)); Assert.assertEquals(c, a.kroneckerProduct(b)); } } @Test public void testTrace_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Assert.assertTrue(Math.abs(a.trace() - 15.0) < Matrices.EPS); } @Test public void testDiagonalProduct_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Assert.assertTrue(Math.abs(a.diagonalProduct() - 45.0) < Matrices.EPS); } @Test public void testProduct_3x3() { Matrix a = m(a(1.0, 1.0, 1.0), a(1.0, 5.0, 1.0), a(1.0, 1.0, 9.0)); Assert.assertTrue(Math.abs(a.product() - 45.0) < Matrices.EPS); } @Test public void testSum_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Assert.assertTrue(Math.abs(a.sum() - 15.0) < Matrices.EPS); } @Test public void testHadamardProduct_3x3() { for (Matrix b: ms(a(9.0, 8.0, 7.0), a(6.0, 5.0, 4.0), a(3.0, 2.0, 1.0))) { Matrix a = m(a(1.0, 2.0, 3.0), a(4.0, 5.0, 6.0), a(7.0, 8.0, 9.0)); Matrix c = m(a(9.0, 16.0, 21.0), a(24.0, 25.0, 24.0), a(21.0, 16.0, 9.0)); Assert.assertEquals(c, a.hadamardProduct(b)); } } @Test public void testHadamardProduct_5x2() { for (Matrix b: ms(a(6.0, 5.0), a(5.0, 4.0), a(4.0, 3.0), a(3.0, 2.0), a(2.0, 1.0))) { Matrix a = m(a(1.0, 2.0), a(2.0, 3.0), a(3.0, 4.0), a(4.0, 5.0), a(5.0, 6.0)); Matrix c = m(a(6.0, 10.0), a(10.0, 12.0), a(12.0, 12.0), a(12.0, 10.0), a(10.0, 6.0)); Assert.assertEquals(c, a.hadamardProduct(b)); } } @Test public void testHadamardProduct_3x4() { for (Matrix b: ms(a(6.0, 5.0, 4.0, 3.0), a(5.0, 4.0, 3.0, 2.0), a(4.0, 3.0, 2.0, 1.0))) { Matrix a = m(a(1.0, 2.0, 3.0, 4.0), a(2.0, 3.0, 4.0, 5.0), a(3.0, 4.0, 5.0, 6.0)); Matrix c = m(a(6.0, 10.0, 12.0, 12.0), a(10.0, 12.0, 12.0, 10.0), a(12.0, 12.0, 10.0, 6.0)); Assert.assertEquals(c, a.hadamardProduct(b)); } } @Test public void testHadamardProduct_1x3() { for (Matrix b: ms(a(6.0, 5.0, 4.0, 3.0))) { Matrix a = m(a(1.0, 2.0, 3.0, 4.0)); Matrix c = m(a(6.0, 10.0, 12.0, 12.0)); Assert.assertEquals(c, a.hadamardProduct(b)); } } @Test public void testDeterminant_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Assert.assertEquals(45.0, a.determinant(), 1e-5); } @Test public void testDeterminant_4x4() { Matrix a = m(a(3.0, 3.0, 4.0, 43.0), a(5.0, 5.0, 6.0, 6.0), a(70.0, 7.0, 8.0, 8.0), a(9.0, 9.0, 10.0, 11.0)); Assert.assertEquals(-9954.0, a.determinant(), 1e-5); } @Test public void testDeterminant_4x4_2() { Matrix a = m(a(1.0, 2.0, 3.0, 4.0), a(1.0, 1.0, 1.0, 1.0), a(2.0, 3.0, 4.0, 5.0), a(2.0, 2.0, 2.0, 2.0)); Assert.assertEquals(0.0, a.determinant(), 1e-5); } @Test public void testDeterminant_7x7() { Matrix a = m(a(1.0, 6.0, -8.0, 5.0, -3.0, 41.0, -2.0), a(-8.0, -5.0, 7.0, 23.0, -7.0, 12.0, -2.0), a(8.0, 77.0, -65.0, 13.0, -8.0, 55.0, -47.0), a(26.0, 27.0, -81.0, -1.0, 10.0, -48.0, -3.0), a(0.0, 34.0, -79.0, 4.0, -1.0, 28.0, 6.0), a(-5.0, 8.0, -20.0, 36.0, -12.0, -7.0, -10.0), a(-6.0, 13.0, 9.0, -4.0, 95.0, 2.0, 46.0)); Assert.assertEquals(-9134649369.0, a.determinant(), 1e-5); } @Test public void testDeterminant_6x6() { Matrix a = m(a(5.0, 89.0, 6.0, 23.0, 6.0, 4.0), a(4.0, 0.0, 27.0, 90.0, 42.0, 12.0), a(6.0, 0.0, 24.0, 9.0, 41.0, 15.0), a(31.0, 0.0, 3.0, 22.0, 2.0, 1.0), a(2.0, 0.0, 37.0, 4.0, 0.0, 21.0), a(23.0, 8.0, 7.0, 0.0, 12.0, 10.0)); Assert.assertEquals(-1695428964.0, a.determinant(), 1e-5); } @Test public void testDeterminant_5x5() { Matrix a = m(a(-10.0, 89.0, -6.0, 23.0, 6.0, 4.0), a(4.0, 5.0, 27.0, 90.0, 0.0, 12.0), a(6.0, 0.0, 0.0, 9.0, 1.0, 15.0), a(31.0, 11.0, 0.0, 12.0, 2.0, 1.0), a(2.0, 0.0, 5.0, 4.0, -1.0, -21.0), a(3.0, -18.0, 7.0, 0.0, 12.0, 10.0)); Assert.assertEquals(3180462.0, a.determinant(), 1e-5); } @Test public void testRank_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Assert.assertEquals(3, a.rank()); } @Test public void testRank_4x4() { Matrix a = m(a(1.0, 0.0, 0.0, 3.5), a(0.0, 0.0, 0.0, 2.0), a(0.0, 0.0, 9.0, 0.0), a(1.0, 0.0, 0.0, 0.0)); Assert.assertEquals(3, a.rank()); } @Test public void testRank_4x4_2() { Matrix a = m(a(1.0, 2.0, 3.0, 4.0), a(1.0, 1.0, 1.0, 1.0), a(2.0, 3.0, 4.0, 5.0), a(2.0, 2.0, 2.0, 2.0)); Assert.assertEquals(2, a.rank()); } @Test public void testRank_2x4() { Matrix a = m(a(1.0, 0.0, 0.0, 3.5), a(0.0, 1.3, 0.0, 2.0)); Assert.assertEquals(2, a.rank()); } @Test public void testRank_5x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 0.0, 0.0), a(1.0, 0.0, 9.0), a(1.0, 0.0, 0.0), a(1.0, 0.0, 0.0)); Assert.assertEquals(2, a.rank()); } @Test public void testRank_10x10() { Matrix a = m(a(15, 6, 84, 67, 4, 11, 81, 47, 57, 41), a(21, 94, 86, 55, 16, 31, 60, 62, 33, 61), a(3, 32, 57, 56, 55, 66, 70, 87, 6, 37), a(71, 48, 8, 24, 43, 61, 56, 24, 37, 63), a(79, 45, 36, 20, 13, 96, 31, 77, 67, 54), a(20, 63, 41, 79, 46, 100, 90, 23, 42, 94), a(15, 10, 36, 18, 25, 81, 76, 29, 23, 53), a(43, 79, 60, 94, 26, 24, 50, 38, 53, 12), a(100, 59, 26, 99, 72, 17, 29, 3, 76, 14), a(18, 38, 141, 123, 59, 77, 151, 134, 63, 78)); Assert.assertEquals(9, a.rank()); } @Test public void testRank_3x6() { Matrix a = m(a(5.0, 7.0, 10.0, 3.0, 5.0, 8.0), a(5.0, 2.0, 3.0, 10.0, 11.0, 9.0), a(4.0, 3.0, 9.0, 12.0, 8.0, 9.0)); Assert.assertEquals(3, a.rank()); } @Test public void testRank_7x11() { Matrix a = m(a(0.0, 13.0, 25.0, 43.0, 81.0, 0.0, 39.0, 60.0, 70.0, 21.0, 44.0, 0.0), a(44.0, 0.0, 13.0, 67.0, 35.0, 0.0, 84.0, 35.0, 23.0, 88.0, 11.0, 0.0), a(5.0, 34.0, 0.0, 143.0, 35.0, 0.0, 65.0, 99.0, 22.0, 13.0, 26.0, 0.0), a(89.0, 23.0, 13.0, 0.0, 78.0, 0.0, 13.0, 24.0, 98.0, 65.0, 0.0, 0.0), a(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), a(56.0, 4.0, 24.0, 56.0, 78.0, 0.0, 13.0, 0.0, 24.0, 57.0, 8.0, 1.0), a(0.0, 0.0, 46.0, 666.0, 34.0, 13.0, 67.0, 9.0, 12.0, 45.0, 38.0, 0.0)); Assert.assertEquals(6, a.rank()); } @Test public void testRank_1x4() { Matrix a = m(a(0.0, 1.0, 0.0, 0.0)); Assert.assertEquals(1, a.rank()); } @Test public void testRank_3x3_empty() { Matrix a = mz(3, 3); Assert.assertEquals(0, a.rank()); } @Test public void testRank_0x0() { Matrix a = mz(0, 0); Assert.assertEquals(0, a.rank()); } @Test public void testRank_7x3() { Matrix a = m(a(1, 2, 0), a(0, 0, 0), a(0, 0, 0), a(0, 0, 0), a(0, 0, 1), a(0, 0, -1), a(1, 2, 1)); Assert.assertEquals(2, a.rank()); } @Test public void testRank_3x1() { Matrix a = m(a(1), a(2), a(0)); Assert.assertEquals(1, a.rank()); } @Test public void testRowAccess_2x1() { Matrix a = m(a(99.0), a(88.0)); Matrix b = m(a(99.0), a(99.0)); a.setRow(1, a.getRow(0)); Assert.assertEquals(b, a); } @Test public void testRowAccess_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Matrix b = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(1.0, 0.0, 0.0)); a.setRow(2, a.getRow(0)); Assert.assertEquals(b, a); } @Test public void testRowAccess_2x4() { Matrix a = m(a(1.0, 0.0, 4.0, 0.0), a(0.0, 5.0, 0.0, 7.0)); Matrix b = m(a(1.0, 0.0, 4.0, 0.0), a(1.0, 0.0, 4.0, 0.0)); a.setRow(1, a.getRow(0)); Assert.assertEquals(b, a); } @Test public void testRowAccess_5x3() { Matrix a = m(a(1.0, 0.0, 4.0), a(0.0, 5.0, 3.0), a(9.0, 0.0, 0.0), a(0.0, 1.0, 8.0), a(2.0, 0.0, 0.0)); Matrix b = m(a(1.0, 0.0, 4.0), a(0.0, 5.0, 3.0), a(9.0, 0.0, 0.0), a(9.0, 0.0, 0.0), a(2.0, 0.0, 0.0)); a.setRow(3, a.getRow(2)); Assert.assertEquals(b, a); } @Test public void testRowAccess_6x4() { Matrix a = m(a(0.0, 18.0, 15.0, 0.0), a(1.0, 0.0, -55.0, 9.0), a(0.0, 0.0, 71.0, 19.0), a(-1.0, -8.0, 54.0, 0.0), a(25.0, 18.0, 0.0, 0.0), a(78.0, 28.0, 0.0, -8.0)); Matrix b = m(a(0.0, 18.0, 15.0, 0.0), a(1.0, 0.0, -55.0, 9.0), a(0.0, 0.0, 71.0, 19.0), a(-1.0, -8.0, 54.0, 0.0), a(25.0, 18.0, 0.0, 0.0), a(25.0, 18.0, 0.0, 0.0)); a.setRow(5, a.getRow(4)); Assert.assertEquals(b, a); } @Test public void testInsertRow_2x3() { Matrix a = m(a(1.0, 0.0, 4.0), a(9.0, 0.0, 0.0)); Vector row = v(a(0.0, 5.0, 3.0)); Matrix b = m(a(1.0, 0.0, 4.0), a(0.0, 5.0, 3.0), a(9.0, 0.0, 0.0)); Assert.assertEquals(b, a.insertRow(1, row)); } @Test public void testInsertColumn_3x2() { Matrix a = m(a(1.0, 4.0), a(0.0, 3.0), a(9.0, 0.0)); Vector column = v(a(0.0, 5.0, 0.0)); Matrix b = m(a(1.0, 0.0, 4.0), a(0.0, 5.0, 3.0), a(9.0, 0.0, 0.0)); Assert.assertEquals(b, a.insertColumn(1, column)); } @Test public void testRemoveRow_3x3() { Matrix a = m(a(1.0, 0.0, 4.0), a(0.0, 5.0, 3.0), a(9.0, 0.0, 0.0)); Matrix b = m(a(1.0, 0.0, 4.0), a(9.0, 0.0, 0.0)); Assert.assertEquals(b, a.removeRow(1)); } @Test public void testRemoveColumn_3x3() { Matrix a = m(a(1.0, 0.0, 4.0), a(0.0, 5.0, 3.0), a(9.0, 0.0, 0.0)); Matrix b = m(a(1.0, 4.0), a(0.0, 3.0), a(9.0, 0.0)); Assert.assertEquals(b, a.removeColumn(1)); } @Test(expected = IndexOutOfBoundsException.class) public void testRemoveRow_3x3_Exception() { Matrix a = m(a(1.0, 0.0, 4.0), a(0.0, 5.0, 3.0), a(9.0, 0.0, 0.0)); a.removeRow(3); } @Test(expected = IndexOutOfBoundsException.class) public void testRemoveColumn_3x3_Exception() { Matrix a = m(a(1.0, 0.0, 4.0), a(0.0, 5.0, 3.0), a(9.0, 0.0, 0.0)); a.removeColumn(3); } @Test(expected = IndexOutOfBoundsException.class) public void testRemoveRow_empty() { Matrix a = mz(0, 0); a.removeFirstRow(); } /** * Returns true if both matrices contain the same elements and have equal * dimensions. * * @param matrix1 Matrix 1 * @param matrix2 Matrix 2 * @return True if both matrices contain the same elements and have equal * dimensions. */ public boolean testWhetherMatricesContainSameElements(Matrix matrix1, Matrix matrix2) { // Test for equal columns and rows if (matrix1.rows() != matrix2.rows()) { return false; } if (matrix1.columns() != matrix2.columns()) { return false; } // Test for same elements double[] a = new double[matrix1.columns() * matrix1.rows()]; int k = 0; for (int i = 0; i < matrix1.rows(); i++) { for (int j = 0; j < matrix1.columns(); j++) { a[k] = matrix1.get(i, j); k++; } } ArrayList b = new ArrayList(); for (int i = 0; i < matrix2.rows(); i++) { for (int j = 0; j < matrix2.columns(); j++) { b.add(matrix2.get(i, j)); } } for (int i = 0; i < a.length; i++) { for (int j = 0; j < b.size(); j++) { if (a[i] == b.get(j)) { b.remove(j); // If match found, remove it from ArrayList to // decrease complexity break; } } } return b.size() == 0; } @Test public void testTestWhetherMatricesContainSameElements() { Matrix a = m(a(1.0, 1.0, 3.0), a(4.0, 5.0, 6.0), a(7.0, 8.0, 9.0)); Matrix b = m(a(1.0, 1.0, 4.0), a(5.0, 6.0, 9.0), a(7.0, 3.0, 8.0)); Assert.assertTrue(testWhetherMatricesContainSameElements(b, a)); Matrix c = m(a(1.0, 1.0, 3.0), a(4.0, 52.0, 6.0), a(7.0, 8.0, 9.0)); Assert.assertFalse(testWhetherMatricesContainSameElements(c, a)); } @Test public void testShuffle_3x2() { Matrix a = m(a(1.0, 2.0), a(4.0, 5.0), a(7.0, 8.0)); Matrix b = a.shuffle(); Assert.assertTrue(testWhetherMatricesContainSameElements(b, a)); } @Test public void testShuffle_5x3() { Matrix a = m(a(1.0, 2.0, 3.0), a(4.0, 5.0, 6.0), a(7.0, 8.0, 9.0), a(10.0, 11.0, 12.0), a(13.0, 14.0, 15.0)); Matrix b = a.shuffle(); Assert.assertTrue(testWhetherMatricesContainSameElements(b, a)); } @Test public void testRotate_3x1() { Matrix a = m(a(1.0), a(3.0), a(5.0)); Matrix b = m(a(5.0, 3.0, 1.0)); Assert.assertEquals(b, a.rotate()); } @Test public void testRotate_2x2() { Matrix a = m(a(1.0, 2.0), a(3.0, 4.0)); Matrix b = m(a(3.0, 1.0), a(4.0, 2.0)); Assert.assertEquals(b, a.rotate()); } @Test public void testRotate_2x4() { Matrix a = m(a(1.0, 2.0, 3.0, 4.0), a(5.0, 6.0, 7.0, 8.0)); Matrix b = m(a(5.0, 1.0), a(6.0, 2.0), a(7.0, 3.0), a(8.0, 4.0)); Assert.assertEquals(b, a.rotate()); } @Test public void testRotate_5x3() { Matrix a = m(a(1.0, 2.0, 3.0), a(4.0, 5.0, 6.0), a(7.0, 8.0, 9.0), a(10.0, 11.0, 12.0), a(13.0, 14.0, 15.0)); Matrix b = m(a(13.0, 10.0, 7.0, 4.0, 1.0), a(14.0, 11.0, 8.0, 5.0, 2.0), a(15.0, 12.0, 9.0, 6.0, 3.0)); Assert.assertEquals(b, a.rotate()); } @Test public void testColumnAccess_2x1() { Matrix a = m(a(11.0, 22.0)); Matrix b = m(a(22.0, 22.0)); a.setColumn(0, a.getColumn(1)); Assert.assertEquals(b, a); } @Test public void testColumnAccess_3x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Matrix b = m(a(1.0, 0.0, 1.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 0.0)); a.setColumn(2, a.getColumn(0)); Assert.assertEquals(b, a); } @Test public void testColumnAccess_2x4() { Matrix a = m(a(1.0, 0.0, 0.0, 4.0), a(0.0, 5.0, 0.0, 9.0)); Matrix b = m(a(1.0, 0.0, 0.0, 1.0), a(0.0, 5.0, 0.0, 0.0)); a.setColumn(3, a.getColumn(0)); Assert.assertEquals(b, a); } @Test public void testColumnAccess_5x3() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 6.0), a(3.0, 0.0, 4.0), a(0.0, 0.0, 0.0), a(2.0, 7.0, 0.0)); Matrix b = m(a(1.0, 1.0, 0.0), a(0.0, 0.0, 6.0), a(3.0, 3.0, 4.0), a(0.0, 0.0, 0.0), a(2.0, 2.0, 0.0)); a.setColumn(1, a.getColumn(0)); Assert.assertEquals(b, a); } @Test public void testColumnAccess_6x4() { Matrix a = m(a(0.0, 18.0, 15.0, 0.0), a(1.0, 0.0, -55.0, 9.0), a(0.0, 0.0, 71.0, 19.0), a(-1.0, -8.0, 54.0, 0.0), a(25.0, 18.0, 0.0, 0.0), a(78.0, 28.0, 0.0, -8.0)); Matrix b = m(a(0.0, 18.0, 15.0, 0.0), a(1.0, 0.0, -55.0, 1.0), a(0.0, 0.0, 71.0, 0.0), a(-1.0, -8.0, 54.0, -1.0), a(25.0, 18.0, 0.0, 25.0), a(78.0, 28.0, 0.0, 78.0)); a.setColumn(3, a.getColumn(0)); Assert.assertEquals(b, a); } @Test public void testCopy_3x3() { Matrix a = m(a(1.0, 2.0, 3.0), a(4.0, 5.0, 6.0), a(7.0, 8.0, 9.0)); Assert.assertEquals(a, a.copy()); } @Test public void testBlank_3x3() { Matrix a = m(a(0.0, 0.0, 3.0), a(0.0, 0.0, 6.0), a(0.0, 0.0, 9.0)); Matrix b = m(a(0.0, 0.0, 0.0), a(0.0, 0.0, 0.0), a(0.0, 0.0, 0.0)); Assert.assertEquals(b, a.blank()); } @Test public void testNormalize_EuclideanNormAccumulator() { Matrix a = m(a(0.0, 3.0), a(4.0, 0.0)); Assert.assertEquals(5.0, a.euclideanNorm(), Matrices.EPS); } @Test public void testNormalize_ManhattanNormAccumulator() { Matrix a = m(a(0.0, 3.0), a(4.0, 0.0)); Assert.assertEquals(7.0, a.manhattanNorm(), Matrices.EPS); } @Test public void testNormalize_InfinityNormAccumulator() { Matrix a = m(a(0.0, 3.0), a(4.0, 0.0)); Assert.assertEquals(4.0, a.infinityNorm(), Matrices.EPS); } @Test public void testPower_2x2() { Matrix a = m(a(1.0, 2.0), a(3.0, 4.0)); Matrix b = m(a(7.0, 10.0), a(15.0, 22.0)); Matrix c = a.power(2); Assert.assertEquals(b, c); Matrix d = m(a(37.0, 54.0), a(81.0, 118.0)); Matrix e = a.power(3); Assert.assertEquals(d, e); Matrix f = m(a(5743.0, 8370.0), a(12555.0, 18298.0)); Matrix g = a.power(6); Assert.assertEquals(f, g); } @Test public void testPower_3x3() { Matrix h = m(a(1.0, 0.0, 0.0), a(4.0, 3.0, 6.0), a(0.0, 0.0, 9.0)); Matrix i = m(a(1.0, 0.0, 0.0), a(160.0, 81.0, 6480.0), a(0.0, 0.0, 6561.0)); Matrix j = h.power(4); Assert.assertEquals(i, j); Matrix k = h.power(1); Assert.assertEquals(h, k); } @Test public void testMax() { Matrix a = m(a(0, 0, -1), a(0, -3, 0), a(6, -7, -2)); Assert.assertEquals(6.0, a.max(), Matrices.EPS); } @Test public void testMaxCompressed() { Matrix a = m(a(0, 0, -1), a(0, -3, 0), a(0, -7, -2)); Assert.assertEquals(0.0, a.max(), Matrices.EPS); } @Test public void testMinCompressed() { Matrix a = m(a(0, 0, 1), a(0, 3, 0), a(0, 7, 2)); Assert.assertEquals(0.0, a.min(), Matrices.EPS); } @Test public void testMin() { Matrix a = m(a(0, 0, -1), a(0, -3, 0), a(0, -7, -2)); Assert.assertEquals(-7.0, a.min(), Matrices.EPS); } @Test public void testMaxInRow() { Matrix a = m(a(0, 0, 1, 0), a(-3, 2, 0, 1), a(-2, 0, 0, -1)); Assert.assertEquals(0.0, a.maxInRow(2), Vectors.EPS); } @Test public void testMinInRow() { Matrix a = m(a(0, 0, 1, 0), a(-3, 2, 0, 1), a(2, 0, 0, 1)); Assert.assertEquals(0.0, a.minInRow(2), Vectors.EPS); } @Test public void testMaxInColumn() { Matrix a = m(a(0, 0, 1, 0), a(-3, 2, 0, 1), a(-2, 0, 0, -1)); Assert.assertEquals(0.0, a.maxInColumn(0), Vectors.EPS); } @Test public void testMinInColumn() { Matrix a = m(a(0, 0, 1, 0), a(-3, 2, 0, 1), a(-2, 0, 0, -1)); Assert.assertEquals(-1.0, a.minInColumn(3), Vectors.EPS); } private Matrix matrixA() { return m(a(8.93, 5.88, 6.57, 9.3, 3.65, 0.08), a(3.96, 8.26, 2.51, 9.61, 4.63, 6.12),// 1 a(7.37, 5.79, 8.8, 0.87, 7.83, 6.15),// 2 a(3.43, 9.08, 1.16, 2.3, 3.66, 4.93),// 3 a(7.05, 7.75, 8.11, 2.93, 9.04, 6.72)); // 4 } @Test(expected = IndexOutOfBoundsException.class) public void testSelect1() { // Throw exception when row indices are invalid Matrix a = matrixA(); int[] rowInd = new int[]{3, 4, 10}; // 10 is too large of a row index int[] colInd = new int[]{0, 1, 2}; a.select(rowInd, colInd); } @Test(expected = IndexOutOfBoundsException.class) public void testSelect2() { // Throw exception when column indices are invalid Matrix a = matrixA(); int[] rowInd = new int[]{0, 1, 2}; int[] colInd = new int[]{-1, 1, 2}; // -1 is a negative column index a.select(rowInd, colInd); } @Test public void testSelect3() { // All columns and a subset of rows selected. Matrix a = matrixA(); int[] rowInd = new int[]{1, 3, 4}; int[] colInd = new int[]{0, 1, 2, 3, 4, 5}; // all columns Matrix b = m(a(3.96, 8.26, 2.51, 9.61, 4.63, 6.12),// 1 a(3.43, 9.08, 1.16, 2.3, 3.66, 4.93),// 3 a(7.05, 7.75, 8.11, 2.93, 9.04, 6.72));// 4 Assert.assertEquals(b, a.select(rowInd, colInd)); } @Test public void testSelect4() { // All rows and a subset of columns selected. Matrix a = matrixA(); int[] rowInd = new int[]{0, 1, 2, 3, 4}; int[] colInd = new int[]{0, 2, 4, 5}; // all columns Matrix c = m(a(8.93, 6.57, 3.65, 0.08),// 0 a(3.96, 2.51, 4.63, 6.12),// 1 a(7.37, 8.8, 7.83, 6.15),// 2 a(3.43, 1.16, 3.66, 4.93),// 3 a(7.05, 8.11, 9.04, 6.72)); // 4 Assert.assertEquals(c, a.select(rowInd, colInd)); } @Test public void testSelect5() { // A subset of rows and columns is selected. Matrix a = matrixA(); int[] rowInd = new int[]{1, 3, 4}; int[] colInd = new int[]{2, 4, 5}; Matrix d = m(a(2.51, 4.63, 6.12), a(1.16, 3.66, 4.93),// 3 a(8.11, 9.04, 6.72)); // 4 Assert.assertEquals(d, a.select(rowInd, colInd)); } @Test public void testSelect6() { // Duplication of rows and columns. Matrix a = matrixA(); int[] rowInd = new int[]{1, 3, 3, 4}; int[] colInd = new int[]{2, 2, 4, 5, 5}; Matrix d = m(a(2.51, 2.51, 4.63, 6.12, 6.12),// 1 a(1.16, 1.16, 3.66, 4.93, 4.93),// 3 a(1.16, 1.16, 3.66, 4.93, 4.93),// 3 a(8.11, 8.11, 9.04, 6.72, 6.72)); // 4 Assert.assertEquals(d, a.select(rowInd, colInd)); } @Test public void testFoldSum() { Matrix d = m(a(6.436, 4.808, 3.923, 5.866), a(7.072, 5.899, 4.771, 3.537), a(7.282, 0.636, 0.010, 3.673), a(5.833, 0.201, 6.941, 5.914), a(5.757, 6.807, 7.830, 2.601), a(0.434, 1.996, 9.329, 1.115)); Vector columnSums = v(32.814, 20.347, 32.804, 22.706); for (int col = 0; col < d.columns(); col++) { double sum = d.foldColumn(col, Vectors.asSumAccumulator(0.0)); Assert.assertEquals(sum, columnSums.get(col), Matrices.EPS); } double[] s = d.foldColumns(Vectors.asSumAccumulator(0.0)); Assert.assertEquals(DenseVector.fromArray(s), columnSums); Vector rowSums = v(21.033, 21.279, 11.601, 18.889, 22.995, 12.874); for (int row = 0; row < d.columns(); row++) { double sum = d.foldRow(row, Vectors.asSumAccumulator(0.0)); Assert.assertEquals(sum, rowSums.get(row), Matrices.EPS); } s = d.foldRows(Vectors.asSumAccumulator(0.0)); Assert.assertEquals(DenseVector.fromArray(s), rowSums); } @Test public void testDiagonalMatrixPredicate() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 1.0, 0.0), a(0.0, 0.0, 1.0)); Assert.assertTrue(a.is(Matrices.DIAGONAL_MATRIX)); Matrix b = m(a(0.0, 0.0, 0.0), a(2.0, 1.0, 0.0), a(0.0, 0.0, 1.0)); Assert.assertFalse(b.is(Matrices.DIAGONAL_MATRIX)); } @Test public void testIdentityMatrixPredicate() { Matrix a = m(a(1.0, 0.0, 0.0), a(0.0, 1.0, 0.0), a(0.0, 0.0, 1.0)); Assert.assertTrue(a.is(Matrices.IDENTITY_MATRIX)); Matrix b = m(a(0.0, 0.0, 0.0), a(1.0, 0.0, 0.0), a(0.0, 0.0, 1.0)); Assert.assertFalse(b.is(Matrices.IDENTITY_MATRIX)); } @Test public void testZeroMatrixPredicate() { Matrix a = m(a(0.0, 0.0, 0.0), a(0.0, 0.0, 0.0)); Assert.assertTrue(a.is(Matrices.ZERO_MATRIX)); Matrix b = m(a(0.0, 0.0, 0.0), a(0.0, 0.0, 0.0), a(0.0, 0.0, 1.0)); Assert.assertFalse(b.is(Matrices.ZERO_MATRIX)); } @Test public void testTridiagonalMatrixPredicate() { Matrix a = m(a(0.0, 1.0, 0.0, 0.0), a(1.0, 2.0, 3.0, 0.0), a(0.0, 1.0, 0.0, 2.0), a(0.0, 0.0, 1.0, 2.0)); Assert.assertTrue(a.is(Matrices.TRIDIAGONAL_MATRIX)); Matrix b = m(a(0.0, 1.0, 0.0, 0.0), a(1.0, 2.0, 3.0, 0.0), a(5.0, 0.0, 0.0, 2.0), a(0.0, 0.0, 1.0, 2.0)); Assert.assertFalse(b.is(Matrices.TRIDIAGONAL_MATRIX)); } @Test public void testSymmetricMatrixPredicate() { Matrix a = m(a(0.0, 1.0, 0.0, 0.0), a(1.0, 2.0, 3.0, 5.0), a(0.0, 3.0, 0.0, 0.0), a(0.0, 5.0, 0.0, 2.0)); Assert.assertTrue(a.is(Matrices.SYMMETRIC_MATRIX)); Matrix b = m(a(0.0, 0.0, 0.0, 0.0), a(0.0, 2.0, 3.0, 0.0), a(3.0, 3.0, 0.0, 0.0), a(0.0, 0.0, 0.0, 2.0)); Assert.assertFalse(b.is(Matrices.SYMMETRIC_MATRIX)); } @Test(expected = IndexOutOfBoundsException.class) public void testGet_IndexCheck_RowNegative() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.get(-1, 1); } @Test(expected = IndexOutOfBoundsException.class) public void testGet_IndexCheck_ColumnNegative() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.get(1, -1); } @Test(expected = IndexOutOfBoundsException.class) public void testGet_IndexCheck_RowTooLarge() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.get(a.rows(), 1); } @Test(expected = IndexOutOfBoundsException.class) public void testGet_IndexCheck_ColumnTooLarge() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.get(1, a.columns()); } @Test public void testGet_IndexCheck_Valid() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); Assert.assertEquals(0.0, a.get(1, 1), 0.0); } @Test(expected = IndexOutOfBoundsException.class) public void testSet_IndexCheck_RowNegative() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.set(-1, 1, 1.0); } @Test(expected = IndexOutOfBoundsException.class) public void testSet_IndexCheck_ColumnNegative() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.set(1, -1, 1.0); } @Test(expected = IndexOutOfBoundsException.class) public void testSet_IndexCheck_RowTooLarge() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.set(a.rows(), 1, 1.0); } @Test(expected = IndexOutOfBoundsException.class) public void testSet_IndexCheck_ColumnTooLarge() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.set(1, a.columns(), 1.0); } @Test public void testSet_IndexCheck_Valid() { Matrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.set(1, 1, 1.0); Assert.assertEquals(1.0, a.get(1, 1), 0.0); } @Test public void testEqualsWithPrecision() throws Exception { Matrix a = mz(0, 0); Assert.assertTrue(a.equals(a, Matrices.EPS)); Assert.assertTrue(a.equals(a.copy(), Matrices.EPS)); Matrix b = mz(2, 2); Matrix c = mz(2, 2); Assert.assertTrue(b.equals(c, Matrices.EPS)); Assert.assertTrue(c.equals(b, Matrices.EPS)); Assert.assertFalse(b.equals(a, Matrices.EPS)); Assert.assertFalse(c.equals(a, Matrices.EPS)); Matrix d = m(a(1.0, 0.0), a(0.0, 1.0)); Assert.assertFalse(d.equals(b, Matrices.EPS)); Assert.assertFalse(d.equals(a, Matrices.EPS)); Matrix e = m(a(Double.MIN_VALUE, Double.MIN_VALUE), a(Double.MIN_VALUE, Double.MIN_VALUE)); Assert.assertTrue(e.equals(b, Matrices.EPS)); Matrix f = m(a(Double.MIN_NORMAL, Double.MIN_NORMAL), a(Double.MIN_NORMAL, Double.MIN_NORMAL)); Assert.assertTrue(f.equals(b, Matrices.EPS)); Assert.assertTrue(f.equals(e, Matrices.EPS)); Assert.assertTrue(b.equals(f, Matrices.EPS)); Assert.assertTrue(e.equals(f, Matrices.EPS)); } @Test public void testEquals() throws Exception { Matrix a = mz(0, 0); Assert.assertTrue(a.equals(a)); Assert.assertTrue(a.copy().equals(a)); Matrix b = mz(2, 2); Matrix c = mz(2, 2); Assert.assertTrue(b.equals(c)); Assert.assertTrue(c.equals(b)); Assert.assertFalse(b.equals(a)); Assert.assertFalse(c.equals(a)); Matrix d = m(a(1.0, 0.0), a(0.0, 1.0)); Assert.assertFalse(d.equals(b)); Assert.assertFalse(d.equals(a)); Matrix e = m(a(Double.MIN_VALUE, Double.MIN_VALUE), a(Double.MIN_VALUE, Double.MIN_VALUE)); Assert.assertTrue(e.equals(b)); Matrix f = m(a(Double.MIN_NORMAL, Double.MIN_NORMAL), a(Double.MIN_NORMAL, Double.MIN_NORMAL)); Assert.assertTrue(f.equals(b)); Assert.assertTrue(f.equals(e)); Assert.assertTrue(b.equals(f)); Assert.assertTrue(e.equals(f)); } @Test public void testFromMatrixMarket() throws Exception { String mm = "%%MatrixMarket matrix coordinate real general\n" + "% This ASCII file represents a sparse 5x5 matrix with 8 \n" + "% nonzeros in the Matrix Market format.\n" + "%\n" + " 5 5 8\n" + " 1 1 1.000e+00\n" + " 2 2 1.050e+01\n" + " 3 3 1.500e-02\n" + " 1 4 6.000e+00\n" + " 4 2 2.505e+02\n" + " 4 4 -2.800e+02\n" + " 4 5 3.332e+01\n" + " 5 5 1.200e+01"; RowMajorSparseMatrix matrix = RowMajorSparseMatrix.zero(5, 5, 8); matrix.set(0, 0, 1.000e+00); matrix.set(1, 1, 1.050e+01); matrix.set(2, 2, 1.500e-02); matrix.set(0, 3, 6.000e+00); matrix.set(3, 1, 2.505e+02); matrix.set(3, 3, -2.800e+02); matrix.set(3, 4, 3.332e+01); matrix.set(4, 4, 1.200e+01); Matrix from_mm_matrix = Matrix.fromMatrixMarket(mm); Assert.assertNotNull(from_mm_matrix); Assert.assertTrue(matrix.equals(from_mm_matrix)); String bcsstm02_mm = "%%MatrixMarket matrix coordinate real general\n" + "16 16 15\n" + "1 1 9.2138580510000e-02\n" + "2 2 9.2138580510000e-02\n" + "3 3 9.2138580510000e-02\n" + "4 4 1.3799573798300e-01\n" + "5 5 1.3799573798300e-01\n" + "6 6 1.3799573798300e-01\n" + "7 7 1.3799573798300e-01\n" + "8 8 1.3799573798300e-01\n" + "9 9 1.3799573798300e-01\n" + "10 10 9.2138580510000e-02\n" + "11 11 9.2138580510000e-02\n" + "12 12 9.2138580510000e-02\n" + "13 13 1.7282857345500e-01\n" + "14 14 1.7282857345500e-01\n" + "15 15 1.7282857345500e-01\n"; RowMajorSparseMatrix bcs_matrix = RowMajorSparseMatrix.zero(16, 16, 15); bcs_matrix.set(0, 0, 9.2138580510000e-02); bcs_matrix.set(1, 1, 9.2138580510000e-02); bcs_matrix.set(2, 2, 9.2138580510000e-02); bcs_matrix.set(3, 3, 1.3799573798300e-01); bcs_matrix.set(4, 4, 1.3799573798300e-01); bcs_matrix.set(5, 5, 1.3799573798300e-01); bcs_matrix.set(6, 6, 1.3799573798300e-01); bcs_matrix.set(7, 7, 1.3799573798300e-01); bcs_matrix.set(8, 8, 1.3799573798300e-01); bcs_matrix.set(9, 9, 9.2138580510000e-02); bcs_matrix.set(10, 10, 9.2138580510000e-02); bcs_matrix.set(11, 11, 9.2138580510000e-02); bcs_matrix.set(12, 12, 1.7282857345500e-01); bcs_matrix.set(13, 13, 1.7282857345500e-01); bcs_matrix.set(14, 14, 1.7282857345500e-01); Matrix bcs_mm_matrix = Matrix.fromMatrixMarket(bcsstm02_mm); Assert.assertNotNull(bcs_mm_matrix); Assert.assertTrue(bcs_matrix.equals(bcs_mm_matrix)); } } la4j-0.6.0/src/test/java/org/la4j/matrix/dense/000077500000000000000000000000001263320764000210645ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/matrix/dense/Basic1DMatrixTest.java000066400000000000000000000016411263320764000251640ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.dense; import org.la4j.Matrices; public class Basic1DMatrixTest extends DenseMatrixTest { public Basic1DMatrixTest() { super(Matrices.BASIC_1D); } } la4j-0.6.0/src/test/java/org/la4j/matrix/dense/Basic2DMatrixTest.java000066400000000000000000000016411263320764000251650ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.dense; import org.la4j.Matrices; public class Basic2DMatrixTest extends DenseMatrixTest { public Basic2DMatrixTest() { super(Matrices.BASIC_2D); } } la4j-0.6.0/src/test/java/org/la4j/matrix/dense/DenseMatrixTest.java000066400000000000000000000027651263320764000250240ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.dense; import org.junit.Assert; import org.junit.Test; import org.la4j.matrix.MatrixFactory; import org.la4j.matrix.MatrixTest; import org.la4j.matrix.DenseMatrix; import static org.la4j.M.*; public abstract class DenseMatrixTest extends MatrixTest { public DenseMatrixTest(MatrixFactory factory) { super(factory); } @Test public void testToArray() { double array[][] = new double[][] { { 1.0, 0.0, 0.0 }, { 0.0, 5.0, 0.0 }, { 0.0, 0.0, 9.0 } }; DenseMatrix a = m(array); double[][] toArray = a.toArray(); for (int i = 0; i < a.rows(); i++) { Assert.assertArrayEquals(array[i], toArray[i], 1e-5); } } } la4j-0.6.0/src/test/java/org/la4j/matrix/sparse/000077500000000000000000000000001263320764000212635ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/matrix/sparse/CCSMatrixTest.java000066400000000000000000000016221263320764000245640ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.sparse; import org.la4j.Matrices; public class CCSMatrixTest extends SparseMatrixTest { public CCSMatrixTest() { super(Matrices.CCS); } } la4j-0.6.0/src/test/java/org/la4j/matrix/sparse/CRSMatrixTest.java000066400000000000000000000016211263320764000246020ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.sparse; import org.la4j.Matrices; public class CRSMatrixTest extends SparseMatrixTest { public CRSMatrixTest() { super(Matrices.CRS); } } la4j-0.6.0/src/test/java/org/la4j/matrix/sparse/SparseMatrixTest.java000066400000000000000000000164261263320764000254210ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.matrix.sparse; import org.junit.Assert; import org.junit.Test; import org.la4j.iterator.MatrixIterator; import org.la4j.matrix.MatrixFactory; import org.la4j.matrix.MatrixTest; import org.la4j.Matrices; import org.la4j.matrix.SparseMatrix; import org.la4j.matrix.functor.MatrixAccumulator; import org.la4j.Vectors; import static org.la4j.M.*; public abstract class SparseMatrixTest extends MatrixTest { public SparseMatrixTest(MatrixFactory factory) { super(factory); } @Test public void testCardinality() { SparseMatrix a = m(a(1.0, 0.0, 0.0), a(0.0, 5.0, 0.0), a(0.0, 0.0, 9.0)); Assert.assertEquals(3, a.cardinality()); } @Test public void testLargeMatrix() { int i = 1000000; int j = 2000000; SparseMatrix a = mz(i, j); Assert.assertEquals(i, a.rows()); Assert.assertEquals(j, a.columns()); for(int x = 0; x < i; x += 100000) { for(int y = 0; y < j; y+= 500000) { a.set(x, y, x * y); } } for(int x = 0; x < i; x += 100000) { for(int y = 0; y < j; y+= 500000) { Assert.assertEquals(x * y, (long) a.get(x, y)); } } } @Test public void testCapacityOverflow() { int i = 65536; int j = 65536; // Integer 65536 * 65536 overflows to 0 Assert.assertEquals(0, i * j); SparseMatrix a = mz(i, j); Assert.assertEquals(i, a.rows()); Assert.assertEquals(j, a.columns()); a.set(0, 0, 42.0); Assert.assertEquals(42.0, a.get(0, 0), Matrices.EPS); a.set(i-1, j-1, 7.0); Assert.assertEquals(7.0, a.get(i-1, j-1), Matrices.EPS); // Since values and Indices array sizes are aligned with CCSMatrix and // CRSMatrix.MINIMUM_SIZE (=32), we need to set more than 32 values. for(int row = 0 ; row < 33 ; row++) { a.set(row, 1, 3.1415); } } @Test public void testIssue141() { int i = 5000000; int j = 7340; // Test overflow Assert.assertTrue(i * j < 0); SparseMatrix a = mz(5000000, 7340); Assert.assertEquals(i, a.rows()); Assert.assertEquals(j, a.columns()); for(int row = 0 ; row < 32 ; row++) { a.set(row, 1, 3.1415); } } @Test public void testFoldNonZero_3x3() { SparseMatrix a = m(a(1.0, 0.0, 2.0), a(4.0, 0.0, 5.0), a(0.0, 0.0, 0.0)); MatrixAccumulator sum = Matrices.asSumAccumulator(0.0); MatrixAccumulator product = Matrices.asProductAccumulator(1.0); Assert.assertEquals(12.0, a.foldNonZero(sum), Matrices.EPS); // check whether the accumulator were flushed or not Assert.assertEquals(12.0, a.foldNonZero(sum), Matrices.EPS); Assert.assertEquals(40.0, a.foldNonZero(product), Matrices.EPS); // check whether the accumulator were flushed or not Assert.assertEquals(40.0, a.foldNonZero(product), Matrices.EPS); Assert.assertEquals(20.0, a.foldNonZeroInRow(1, Vectors.asProductAccumulator(1.0)), Matrices.EPS); Assert.assertEquals(10.0, a.foldNonZeroInColumn(2, Vectors.asProductAccumulator(1.0)), Matrices.EPS); double[] nonZeroInColumns = a.foldNonZeroInColumns(Vectors.asProductAccumulator(1.0)); Assert.assertArrayEquals(new double[]{4.0, 1.0, 10.0}, nonZeroInColumns, 1e-5); double[] nonZeroInRows = a.foldNonZeroInRows(Vectors.asProductAccumulator(1.0)); Assert.assertArrayEquals(new double[]{2.0, 20.0, 1.0}, nonZeroInRows, 1e-5); } @Test public void testIsZeroAt_5x3() { SparseMatrix a = m(a(1.0, 0.0, 0.0), a(0.0, 0.0, 2.0), a(0.0, 0.0, 0.0), a(0.0, 3.0, 0.0), a(0.0, 0.0, 0.0)); Assert.assertTrue(a.isZeroAt(2, 2)); Assert.assertFalse(a.isZeroAt(3, 1)); } @Test public void testNonZeroAt_3x4() { SparseMatrix a = m(a(0.0, 0.0, 2.0, 0.0), a(0.0, 0.0, 0.0, 0.0), a(0.0, 1.0, 0.0, 0.0)); Assert.assertTrue(a.nonZeroAt(2, 1)); Assert.assertFalse(a.nonZeroAt(0, 3)); } @Test public void testGetOrElse_2x5() { SparseMatrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); Assert.assertEquals(0.0, a.getOrElse(0, 2, 0.0), Matrices.EPS); Assert.assertEquals(3.0, a.getOrElse(1, 2, 3.14), Matrices.EPS); Assert.assertEquals(4.2, a.getOrElse(1, 3, 4.2), Matrices.EPS); } @Test(expected = IndexOutOfBoundsException.class) public void testGetOrElse_IndexCheck_RowNegative() { SparseMatrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.getOrElse(-1, 1, 0.0); } @Test(expected = IndexOutOfBoundsException.class) public void testGetOrElse_IndexCheck_ColumnNegative() { SparseMatrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.getOrElse(1, -1, 0.0); } @Test(expected = IndexOutOfBoundsException.class) public void testGetOrElse_IndexCheck_RowTooLarge() { SparseMatrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.getOrElse(a.rows(), 1, 0.0); } @Test(expected = IndexOutOfBoundsException.class) public void testGetOrElse_IndexCheck_ColumnTooLarge() { SparseMatrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); a.getOrElse(1, a.columns(), 0.0); } @Test public void testGetOrElse_IndexCheck_Valid() { SparseMatrix a = m(a(0.0, 0.0, 0.0, 1.0, 0.0), a(0.0, 0.0, 3.0, 0.0, 0.0)); Assert.assertEquals(0.0, a.getOrElse(1, 1, 0.0), 0.0); } @Test public void testNonZeroIterator_issue253() { SparseMatrix a = m(a(0.0, 0.0, 0.0, 1.0, 1.0), a(0.0, 0.0, 0.0, 0.0, 0.0), a(0.0, 0.0, 0.0, 0.0, 0.0), a(1.0, 0.0, 0.0, 0.0, 1.0), a(1.0, 0.0, 0.0, 1.0, 0.0)); MatrixIterator it = a.nonZeroIterator(); while (it.hasNext()) { double x = it.next(); int i = it.rowIndex(); int j = it.columnIndex(); Assert.assertEquals(x, a.get(i, j), 1e-4); } } } la4j-0.6.0/src/test/java/org/la4j/vector/000077500000000000000000000000001263320764000177645ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/vector/VectorTest.java000066400000000000000000000522321263320764000227350ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): Daniel Renshaw * Jakob Moellers * Yuriy Drozd * Maxim Samoylov * */ package org.la4j.vector; import org.junit.Assert; import org.junit.Test; import org.la4j.V; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.Matrix; import org.la4j.vector.functor.VectorAccumulator; import org.la4j.vector.functor.VectorPredicate; import static org.la4j.V.*; import static org.la4j.M.*; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; public abstract class VectorTest { protected VectorFactory factory; public VectorTest(VectorFactory factory) { this.factory = factory; } public T v(double... values) { return V.v(values).to(factory); } public T vz(int length) { return V.vz(length).to(factory); } @Test public void testAccess_10() { Vector a = v(0.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.1, 2.0); Assert.assertEquals(10, a.length()); Assert.assertEquals(0.0, a.get(0), Vectors.EPS); Assert.assertEquals(2.0, a.get(2), Vectors.EPS); Assert.assertEquals(2.0, a.get(9), Vectors.EPS); a.set(3, 42.0); a.set(8, 14.0); a.set(0, 3.3); Assert.assertEquals(42.0, a.get(3), Vectors.EPS); Assert.assertEquals(14.0, a.get(8), Vectors.EPS); Assert.assertEquals(3.3, a.get(0), Vectors.EPS); } @Test public void testSetAll_5() { Vector a = v(0.0, 0.0, 0.0, 0.0, 1.0, 4.0); a.setAll(11.1); for (double d: a) { Assert.assertEquals(11.1, d, Vectors.EPS); } } @Test public void testCopyOfLength_3_to_5_to_2() { Vector a = v(0.0, 0.0, 1.0); Vector b = v(0.0, 0.0, 1.0, 0.0, 0.0); Vector c = v(0.0, 0.0); a = a.copyOfLength(5); Assert.assertEquals(b, a); a = a.copyOfLength(2); Assert.assertEquals(c, a); } @Test public void testCopyOf_5_to_0_to_4() { Vector a = v(0.0, 1.0, 2.0, 3.0, 0.0); Vector b = v(); Vector c = v(0.0, 0.0, 0.0, 0.0); a = a.copyOfLength(0); Assert.assertEquals(b, a); a = a.copyOfLength(4); Assert.assertEquals(c, a); } @Test public void testSlice_5_to_2_and_3() { Vector a = v(1.0, 2.0, 3.0, 4.0, 5.0); Vector b = v(2.0, 3.0); Vector c = v(3.0, 4.0, 5.0); Assert.assertEquals(b, a.slice(1, 3)); Assert.assertEquals(c, a.slice(2, 5)); } @Test public void testSliceLeftRight_5_to_1_and_4() { Vector a = v(0.0, 2.0, 0.0, 4.0, 0.0); Vector b = v(0.0); Vector c = v(2.0, 0.0, 4.0, 0.0); Assert.assertEquals(b, a.sliceLeft(1)); Assert.assertEquals(c, a.sliceRight(1)); } @Test public void testSelect_4() { Vector a = v(0.0, 3.0, 7.0, 0.0); Vector b = v(3.0, 0.0, 0.0, 7.0); Vector c = v(7.0, 7.0, 0.0, 0.0); Assert.assertEquals(b, a.select(new int[]{1, 0, 3, 2})); Assert.assertEquals(c, a.select(new int[]{2, 2, 0, 3})); } @Test public void testSelect_5() { Vector a = v(1.0, 6.0, 0.0, 0.0, 8.0); Vector b = v(1.0, 1.0, 1.0); Vector c = v(0.0, 0.0, 8.0, 8.0, 1.0, 0.0); Assert.assertEquals(b, a.select(new int[]{0, 0, 0})); Assert.assertEquals(c, a.select(new int[]{2, 3, 4, 4, 0, 3})); } @Test public void testSelect_3() { Vector a = v(1.0, 0.0, 0.0); Vector b = v(0.0, 0.0, 0.0, 0.0); Vector c = v(1.0); Assert.assertEquals(b, a.select(new int[]{1, 2, 2, 1})); Assert.assertEquals(c, a.select(new int[]{0})); } @Test public void testSwapElements_5() { Vector a = v(1.0, 0.0, 0.0, 0.0, 3.0); Vector b = v(3.0, 0.0, 0.0, 0.0, 1.0); a.swapElements(0, 4); Assert.assertEquals(b, a); } @Test public void testSwapElements_4() { Vector a = v(0.0, 1.0, 0.0, 0.0); Vector b = v(0.0, 0.0, 1.0, 0.0); a.swapElements(1, 2); Assert.assertEquals(b, a); } @Test public void testSwapElements_4_2() { Vector a = v(0.0, 1.0, 0.0, 2.0); Vector b = v(0.0, 0.0, 1.0, 2.0); a.swapElements(1, 2); Assert.assertEquals(a, b); } @Test public void testSwapElements_6() { Vector a = v(0.0, 0.0, 0.0, 0.0, 0.0, -5.0); Vector b = v(0.0, 0.0, 0.0, -5.0, 0.0, 0.0); a.swapElements(3, 5); Assert.assertEquals(a, b); } @Test public void testSwapElements_2() { Vector a = v(1.0, 2.0); Vector b = v(2.0, 1.0); a.swapElements(0, 1); Assert.assertEquals(b, a); } @Test public void testEuclideanNorm_3() { Vector a = v(1.0, 2.0, 3.0); Assert.assertEquals(3.74165, a.fold(Vectors.mkEuclideanNormAccumulator()), 1e-5); Assert.assertEquals(3.74165, a.euclideanNorm(), 1e-5); } @Test public void testEuclideanNorm_5() { Vector a = v(1.0, 0.0, 3.0, 0.0, -5.0); Assert.assertEquals(5.91607, a.fold(Vectors.mkEuclideanNormAccumulator()), 1e-5); Assert.assertEquals(5.91607, a.euclideanNorm(), 1e-5); } @Test public void testManhattanNorm_3() { Vector a = v(1.0, 2.0, 3.0); Assert.assertEquals(6.0, a.fold(Vectors.mkManhattanNormAccumulator()), 1e-5); Assert.assertEquals(6.0, a.manhattanNorm(), 1e-5); } @Test public void testManhattanNorm_5() { Vector a = v(1.0, 0.0, 3.0, 0.0, -5.0); Assert.assertEquals(9.0, a.fold(Vectors.mkManhattanNormAccumulator()), 1e-5); Assert.assertEquals(9.0, a.manhattanNorm(), 1e-5); } @Test public void testInfinityNorm_3() { Vector a = v(1.0, 2.0, 3.0); Assert.assertEquals(3.0, a.fold(Vectors.mkInfinityNormAccumulator()), 1e-5); Assert.assertEquals(3.0, a.infinityNorm(), 1e-5); } @Test public void testInfinityNorm_5() { Vector a = v(1.0, 0.0, 3.0, 0.0, -5.0); Assert.assertEquals(5.0, a.fold(Vectors.mkInfinityNormAccumulator()), 1e-5); Assert.assertEquals(5.0, a.infinityNorm(), 1e-5); } @Test public void testAdd_3() { for (Vector b: vs(0.0, 5.0, 0.0)) { Vector a = v(0.0, 0.0, 3.0); Vector c = v(7.0, 7.0, 10.0); Vector d = v(0.0, 5.0, 3.0); Assert.assertEquals(c, a.add(7.0)); Assert.assertEquals(d, a.add(b)); Assert.assertEquals(d, b.add(a)); } } @Test public void testAdd_4() { for (Vector b: vs(0.0, 1.0, 0.0, 6.0)) { Vector a = v(1.0, 0.0, 0.0, 3.0); Vector c = v(1.0, 1.0, 0.0, 9.0); Assert.assertEquals(c, a.add(b)); Assert.assertEquals(c, b.add(a)); } } @Test public void testSubtract_3() { for (Vector b: vs(4.0, 0.0, 0.0)) { Vector a = v(0.0, 0.0, 3.0); Vector c = v(-7.0, -7.0, -4.0); Vector d = v(-4.0, 0.0, 3.0); Assert.assertEquals(c, a.subtract(7.0)); Assert.assertEquals(d, a.subtract(b)); } } @Test public void testMultiply_3() { for (Vector b: vs(0.0, 5.0, 0.0)) { Vector a = v(0.0, 0.0, 1.0); Vector c = v(0.0, 0.0, 10.0); Vector d = v(0.0, 0.0, 0.0); Assert.assertEquals(c, a.multiply(10.0)); Assert.assertEquals(d, a.hadamardProduct(b)); } } @Test public void testHadamardProduct_3() { for (Vector b: vs(3.0, 0.0, 0.0)) { Vector a = v(1.0, 0.0, 2.0); Vector c = v(3.0, 0.0, 0.0); Assert.assertEquals(c, a.hadamardProduct(b)); } } @Test public void testMultiply_2_2x4() { for (Matrix b: ms(a(0.0, 5.0, 0.0, 6.0), a(1.0, 0.0, 8.0, 0.0))) { Vector a = v(1.0, 2.0); Vector c = v(2.0, 5.0, 16.0, 6.0); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testMultiply_3_3x1() { for (Matrix b: ms(a(0.0), a(3.0), a(0.0))) { Vector a = v(0.0, 2.0, 0.0); Vector c = v(6.0); Assert.assertEquals(c, a.multiply(b)); } } @Test public void testProduct_3() { Vector a = v(2.0, 4.0, 6.0); Assert.assertEquals(a.product(), 48.0, Vectors.EPS); } @Test public void testSum_3() { Vector a = v(2.0, 4.0, 6.0); Assert.assertEquals(a.sum(), 12.0, Vectors.EPS); } @Test public void testDivide_3() { Vector a = v(0.0, 0.0, 3.0); Vector b = v(0.0, 0.0, 0.3); Assert.assertEquals(b, a.divide(10)); } @Test public void testCopy_5() { Vector a = v(0.0, 0.0, 0.0, 0.0, 1.0); Assert.assertEquals(a, a.copy()); } @Test public void testBlank_5() { Vector a = v(0.0, 0.0, 0.0, 0.0, 1.0); Vector b = v(0.0, 0.0, 0.0, 0.0, 0.0); Assert.assertEquals(b, a.blank()); } @Test public void testInnerProduct_1() { for (Vector b: vs(10.0)) { Vector a = v(18.0); Assert.assertEquals(180.0, a.innerProduct(b), Vectors.EPS); } } @Test public void testInnerProduct_3() { for (Vector b: vs(10.0, 0.0, 10.0)) { Vector a = v(1.0, 2.0, 3.0); Assert.assertEquals(40.0, a.innerProduct(b), Vectors.EPS); } } @Test public void testInnerProduct_4() { for (Vector b: vs(11.0, 13.0, 17.0, 19.0)) { Vector a = v(2.0, 3.0, 5.0, 7.0); Assert.assertEquals(279.0, a.innerProduct(b), Vectors.EPS); } } @Test public void testOuterProduct_3_4() { for (Vector b: vs(7.0, 11.0, 13.0, 17.0)) { Vector a = v(2.0, 3.0, 5.0); Matrix c = m(a(14.0, 22.0, 26.0, 34.0), a(21.0, 33.0, 39.0, 51.0), a(35.0, 55.0, 65.0, 85.0)); Assert.assertEquals(c, a.outerProduct(b)); } } @Test public void testOuterProduct_1_2() { for (Vector b: vs(24.0, 1.0)) { Vector a = v(2.0); Matrix c = m(a(48.0, 2.0)); Assert.assertEquals(c, a.outerProduct(b)); } } @Test public void testOuterProduct_4_2() { for (Vector b: vs(4.0, -10.0)) { Vector a = v(2.0, 0.0, -1.0, 41.0); Matrix c = m(a(8.0, -20.0), a(0.0, 0.0), a(-4.0, 10.0), a(164.0, -410.0)); Assert.assertEquals(c, a.outerProduct(b)); } } /** * Tests whether two vectors contain the same elements * * @param vector1 Vector1 * @param vector2 Vector2 * @return True if both vectors contain the same elements */ public boolean testWhetherVectorsContainSameElements(Vector vector1, Vector vector2) { if (vector1.length() == vector2.length()) { boolean[] checkList = new boolean[vector1.length()]; for (int i = 0; i < vector1.length(); i++) { for (int j = 0; j < vector2.length(); j++) { if (vector1.get(i) == vector2.get(j)) { if (!checkList[j]) { checkList[j] = true; break; } } } } boolean result = true; for (int i = 0; i < checkList.length; i++) { if (!checkList[i]) { result = false; } } return result; } else { return false; } } @Test public void testTestWhetherVectorsContainSameElements() { Vector a = v(1.0, 1.0, 3.0, 4.0); Vector b = v(4.0, 1.0, 1.0, 3.0); Vector c = v(4.0, 2.0, 1.0, 3.0); Assert.assertTrue(testWhetherVectorsContainSameElements(a, b)); Assert.assertFalse(testWhetherVectorsContainSameElements(a, c)); } @Test public void testShuffle() { Vector a = v(1.0, 1.0, 3.0, 4.0); Vector b = a.shuffle(); Assert.assertTrue(testWhetherVectorsContainSameElements(a, b)); } @Test public void testMax() { Vector a = v(1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -5.0, 0.0, 0.0, 5.0); Assert.assertEquals(5.0, a.max(), Vectors.EPS); } @Test public void testMaxCompressed() { Vector a = v(0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -5.0, 0.0, 0.0); Assert.assertEquals(0.0, a.max(), Vectors.EPS); } @Test public void testMin() { Vector a = v(1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -5.0, 0.0, 0.0, 5.0); Assert.assertEquals(-5.0, a.min(), Vectors.EPS); } @Test public void testMinCompressed() { Vector a = v(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.0); Assert.assertEquals(0.0, a.min(), Vectors.EPS); } @Test public void testFold_6() { Vector a = v(0.0, 0.0, 5.0, 0.0, 2.0, 1.0); VectorAccumulator sum = Vectors.asSumAccumulator(0.0); VectorAccumulator product = Vectors.asProductAccumulator(1.0); Assert.assertEquals(8.0, a.fold(sum), Vectors.EPS); // check whether the accumulator were flushed Assert.assertEquals(8.0, a.fold(sum), Vectors.EPS); Assert.assertEquals(0.0, a.fold(product), Vectors.EPS); // check whether the accumulator were flushed Assert.assertEquals(0.0, a.fold(product), Vectors.EPS); } @Test public void testIssue162_0() { VectorPredicate pi = new VectorPredicate() { @Override public boolean test(int i, double value) { return value == 3.14; } }; Vector a = v(); Vector b = a.copyOfLength(31); Assert.assertEquals(0, a.length()); Assert.assertEquals(31, b.length()); b.setAll(3.14); Assert.assertTrue(b.is(pi)); Vector c = b.copyOfLength(42); c.setAll(3.14); Assert.assertTrue(c.is(pi)); Vector d = c.copyOfLength(54); d.setAll(3.14); Assert.assertTrue(d.is(pi)); } @Test public void testResize_32_to_110_to_1076_to_31() { VectorPredicate fortyTwo = new VectorPredicate() { @Override public boolean test(int i, double value) { return value == 42.0; } }; Vector a = v(); Vector b = a.copyOfLength(32); Assert.assertEquals(32, b.length()); b.setAll(42.0); Assert.assertTrue(b.is(fortyTwo)); Vector c = b.copyOfLength(110); c.setAll(42.0); Assert.assertTrue(c.is(fortyTwo)); Vector d = c.copyOfLength(1076); d.setAll(42.0); Assert.assertTrue(d.is(fortyTwo)); Vector e = d.copyOfLength(31); e.setAll(42.0); Assert.assertTrue(e.is(fortyTwo)); } @Test public void testNormalize_Default() { Vector a = v(3.0, 0.0, -4.0); Vector b = a.divide(a.norm()); Assert.assertEquals(3, b.length()); Assert.assertEquals(0.6, b.get(0), Vectors.EPS); Assert.assertEquals(0.0, b.get(1), Vectors.EPS); Assert.assertEquals(-0.8, b.get(2), Vectors.EPS); // Verify b is a unit vector // The default normalize() uses Euclidean as the accumulator Assert.assertEquals(1.0, b.norm(), Vectors.EPS); } @Test public void testNormalize_EuclideanNormAccumulator() { Vector a = v(3.0, 0.0, -4.0); Vector b = a.divide(a.euclideanNorm()); Assert.assertEquals(3, b.length()); Assert.assertEquals(0.6, b.get(0), Vectors.EPS); Assert.assertEquals(0.0, b.get(1), Vectors.EPS); Assert.assertEquals(-0.8, b.get(2), Vectors.EPS); // Verify b is a unit vector Assert.assertEquals(1.0, b.euclideanNorm(), Vectors.EPS); } @Test public void testNormalize_ManhattanNormAccumulator() { Vector a = v(3.0, 0.0, -4.0); Vector b = a.divide(a.manhattanNorm()); Assert.assertEquals(3, b.length()); Assert.assertEquals(0.42857, b.get(0), 0.00001); Assert.assertEquals(0.0, b.get(1), Vectors.EPS); Assert.assertEquals(-0.57142, b.get(2), 0.00001); // Verify b is a unit vector Assert.assertEquals(1.0, b.manhattanNorm(), Vectors.EPS); } @Test public void testNormalize_InfinityNormAccumulator() { Vector a = v(3.0, 0.0, -4.0); Vector b = a.divide(a.infinityNorm()); Assert.assertEquals(3, b.length()); Assert.assertEquals(0.75, b.get(0), Vectors.EPS); Assert.assertEquals(0.0, b.get(1), Vectors.EPS); Assert.assertEquals(-1.0, b.get(2), Vectors.EPS); // Verify b is a unit vector Assert.assertEquals(1.0, b.infinityNorm(), Vectors.EPS); } @Test public void testEqualsWithPrecision() throws Exception { Vector a = v(1000.0, 1.0); Assert.assertTrue(a.equals(a, Vectors.EPS)); Vector b = v().copyOfLength(1000); b.setAll(42.0); Assert.assertFalse(a.equals(b, Vectors.EPS)); Assert.assertFalse(b.equals(a, Vectors.EPS)); Vector e = v(); Assert.assertTrue(e.equals(e, Vectors.EPS)); Vector f = v(Double.MIN_VALUE, Double.MIN_VALUE); Vector g = vz(2); Assert.assertTrue(f.equals(g, Vectors.EPS)); Assert.assertTrue(g.equals(f, Vectors.EPS)); Vector i = v(Double.MIN_NORMAL, Double.MIN_NORMAL); Assert.assertTrue(i.equals(g, Vectors.EPS)); Assert.assertTrue(i.equals(f, Vectors.EPS)); Assert.assertTrue(g.equals(i, Vectors.EPS)); Assert.assertTrue(f.equals(i, Vectors.EPS)); } @Test public void testEquals() throws Exception { Vector a = v().copyOfLength(1000); a.setAll(1.0); Assert.assertTrue(a.equals(a)); Assert.assertTrue(a.copy().equals(a)); Vector d = v().copyOfLength(1000); Assert.assertFalse(d.equals(a)); Assert.assertTrue(d.equals(d.copy())); Vector e = v(); Assert.assertTrue(e.equals(e.copy())); Vector f = v(Double.MIN_VALUE); Vector g = v(0.0); Assert.assertTrue(f.equals(g)); Assert.assertTrue(g.equals(f)); Vector i = v(Double.MIN_NORMAL); Assert.assertTrue(i.equals(g)); Assert.assertTrue(i.equals(f)); Assert.assertTrue(g.equals(i)); Assert.assertTrue(f.equals(i)); } @Test public void testFromCollection_empty() { List values = new LinkedList<>(); Assert.assertEquals(Vector.fromCollection(values), Vector.zero(0)); } @Test public void testFromCollection_normal_x3() { List values = Arrays.asList(1.0, 2.0, 3.0); Vector v = Vector.fromCollection(values); Assert.assertEquals(v, Vector.fromArray(new double[] {1.0, 2.0, 3.0})); } @Test public void testFromCollection_byte() { List values = Arrays.asList((byte) 1, (byte) 3, (byte) 5, (byte) 6); Vector v = Vector.fromCollection(values); Assert.assertEquals(v, Vector.fromArray(new double[] {1.0, 3.0, 5.0, 6.0})); } @Test(expected = NullPointerException.class) public void testFromCollection_NPE() { Vector v = Vector.fromCollection(null); } @Test public void testFromMap_empty() { Map map = new HashMap<>(); Assert.assertEquals(Vector.fromMap(map, 0), Vector.zero(0)); } @Test public void testFromMap_normal() { Map map = new HashMap<>(); map.put(0, 1.0); map.put(3, 2.0); map.put(5, 1.0); Vector v = Vector.fromArray(new double[]{1, 0, 0, 2, 0, 1, 0}); Assert.assertEquals(v, Vector.fromMap(map, 7)); } @Test public void testFromMap_emptyMap() { Map map = new HashMap<>(); Assert.assertEquals(Vector.fromMap(map, 5), Vector.zero(5)); } @Test(expected = IllegalArgumentException.class) public void testFromMap_invalidMap() { Map map = new HashMap<>(); map.put(0, 1.0); map.put(3, 2.0); map.put(-2, 1.0); Vector v = Vector.fromMap(map, 5); } @Test(expected = NullPointerException.class) public void testFromMap_NPE() { Vector v = Vector.fromMap(null, 4); } } la4j-0.6.0/src/test/java/org/la4j/vector/dense/000077500000000000000000000000001263320764000210625ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/vector/dense/BasicVectorTest.java000066400000000000000000000016261263320764000247760ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.dense; import org.la4j.Vectors; public class BasicVectorTest extends DenseVectorTest { public BasicVectorTest() { super(Vectors.BASIC); } } la4j-0.6.0/src/test/java/org/la4j/vector/dense/DenseVectorTest.java000066400000000000000000000024531263320764000250120ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.dense; import java.util.Arrays; import org.junit.Assert; import org.junit.Test; import org.la4j.vector.VectorFactory; import org.la4j.vector.VectorTest; import org.la4j.vector.DenseVector; public abstract class DenseVectorTest extends VectorTest { public DenseVectorTest(VectorFactory factory) { super(factory); } @Test public void testToArray() { double array[] = new double[] { 0.0, 0.0, 0.0, 0.0, 1.0 }; DenseVector a = v(array); Assert.assertTrue(Arrays.equals(array, a.toArray())); } } la4j-0.6.0/src/test/java/org/la4j/vector/sparse/000077500000000000000000000000001263320764000212615ustar00rootroot00000000000000la4j-0.6.0/src/test/java/org/la4j/vector/sparse/CompressedVectorTest.java000066400000000000000000000016541263320764000262610ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.sparse; import org.la4j.Vectors; public class CompressedVectorTest extends SparseVectorTest { public CompressedVectorTest() { super(Vectors.COMPRESSED); } } la4j-0.6.0/src/test/java/org/la4j/vector/sparse/SparseVectorTest.java000066400000000000000000000104111263320764000254010ustar00rootroot00000000000000/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * 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. * * Contributor(s): - * */ package org.la4j.vector.sparse; import org.junit.Assert; import org.junit.Test; import org.la4j.vector.VectorFactory; import org.la4j.vector.VectorTest; import org.la4j.Vectors; import org.la4j.vector.SparseVector; import org.la4j.vector.functor.VectorAccumulator; public abstract class SparseVectorTest extends VectorTest { public SparseVectorTest(VectorFactory factory) { super(factory); } @Test public void testCardinality() { SparseVector a = v(0.0, 0.0, 0.0, 0.0, 1.0); Assert.assertEquals(1, a.cardinality()); } @Test public void testFoldNonZero_5() { SparseVector a = v(2.0, 0.0, 5.0, 0.0, 2.0); VectorAccumulator sum = Vectors.asSumAccumulator(0.0); VectorAccumulator product = Vectors.asProductAccumulator(1.0); Assert.assertEquals(9.0, a.foldNonZero(sum), Vectors.EPS); // check whether the accumulator were flushed Assert.assertEquals(9.0, a.foldNonZero(sum), Vectors.EPS); Assert.assertEquals(20.0, a.foldNonZero(product), Vectors.EPS); // check whether the accumulator were flushed Assert.assertEquals(20.0, a.foldNonZero(product), Vectors.EPS); } @Test public void testIsZeroAt_4() { SparseVector a = v(1.0, 0.0, 0.0, 4.0); Assert.assertTrue(a.isZeroAt(1)); Assert.assertFalse(a.isZeroAt(3)); } @Test public void testNonZeroAt_6() { SparseVector a = v(0.0, 5.0, 2.0, 0.0, 0.0, 0.0); Assert.assertTrue(a.nonZeroAt(1)); Assert.assertFalse(a.nonZeroAt(3)); } @Test public void testGetOrElse_5() { SparseVector a =v(0.0, 0.0, 1.0, 0.0, 0.0); Assert.assertEquals(0.0, a.getOrElse(1, 0.0), Vectors.EPS); Assert.assertEquals(1.0, a.getOrElse(2, 3.14), Vectors.EPS); Assert.assertEquals(4.2, a.getOrElse(3, 4.2), Vectors.EPS); } @Test(expected = IndexOutOfBoundsException.class) public void testGet_IndexCheck_Negative() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); a.get(-1); } @Test(expected = IndexOutOfBoundsException.class) public void testGet_IndexCheck_TooLarge() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); a.get(a.length()); } @Test public void testGet_IndexCheck_Valid() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); Assert.assertEquals(1.0, a.get(2), 0.0); } @Test(expected=IndexOutOfBoundsException.class) public void testGetOrElse_IndexCheck_Negative() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); a.getOrElse(-1, 0.0); } @Test(expected=IndexOutOfBoundsException.class) public void testGetOrElse_IndexCheck_TooLarge() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); a.getOrElse(a.length(), 0.0); } @Test public void testGetOrElse_IndexCheck_Valid() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); Assert.assertEquals(1.0, a.getOrElse(2, 0.0), 0.0); } @Test(expected = IndexOutOfBoundsException.class) public void testSet_IndexCheck_Negative() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); a.set(-1, 1.0); } @Test(expected = IndexOutOfBoundsException.class) public void testSet_IndexCheck_TooLarge() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); a.set(a.length(), 1.0); } @Test public void testSet_IndexCheck_Valid() { SparseVector a = v(0.0, 0.0, 1.0, 0.0, 0.0); a.set(0, 1.0); Assert.assertEquals(1.0, a.get(0), 0.0); } }