Repository: scalala/Scalala Branch: master Commit: 6206a4601322 Files: 173 Total size: 1.0 MB Directory structure: gitextract_e_sqcedj/ ├── .gitignore ├── LICENSE ├── README ├── build.sbt ├── project/ │ ├── build.properties │ └── plugins.sbt ├── sbt └── src/ ├── main/ │ ├── java/ │ │ └── scalala/ │ │ └── library/ │ │ └── random/ │ │ └── MersenneTwisterFast.java │ ├── resources/ │ │ └── scalala.scala │ └── scala/ │ └── scalala/ │ ├── ScalalaConsole.scala │ ├── collection/ │ │ └── sparse/ │ │ └── SparseArray.scala │ ├── generic/ │ │ ├── collection/ │ │ │ ├── CanAppendColumns.scala │ │ │ ├── CanBuildTensorForBinaryOp.scala │ │ │ ├── CanBuildTensorFrom.scala │ │ │ ├── CanCopy.scala │ │ │ ├── CanCreateZerosLike.scala │ │ │ ├── CanFilterValues.scala │ │ │ ├── CanGetActiveValues.scala │ │ │ ├── CanGetDouble.scala │ │ │ ├── CanGetValue.scala │ │ │ ├── CanJoin.scala │ │ │ ├── CanMapKeyValuePairs.scala │ │ │ ├── CanMapValues.scala │ │ │ ├── CanSliceMatrix.scala │ │ │ ├── CanSliceTensor.scala │ │ │ ├── CanSliceVector.scala │ │ │ ├── CanTranspose.scala │ │ │ ├── CanView.scala │ │ │ ├── CanViewAsTensor1.scala │ │ │ ├── CanViewAsTensor2.scala │ │ │ ├── CanViewAsVector.scala │ │ │ └── CanZipMapValues.scala │ │ └── math/ │ │ ├── CanAbs.scala │ │ ├── CanExp.scala │ │ ├── CanLog.scala │ │ ├── CanMean.scala │ │ ├── CanNorm.scala │ │ ├── CanSoftmax.scala │ │ ├── CanSqrt.scala │ │ └── CanVariance.scala │ ├── library/ │ │ ├── Library.scala │ │ ├── LinearAlgebra.scala │ │ ├── Numerics.scala │ │ ├── Plotting.scala │ │ ├── Random.scala │ │ ├── Statistics.scala │ │ ├── Storage.scala │ │ └── plotting/ │ │ ├── Dataset.scala │ │ ├── ExportGraphics.scala │ │ ├── Figure.scala │ │ ├── Figures.scala │ │ ├── HistogramBins.scala │ │ ├── PaintScale.scala │ │ ├── PaintScaleFactory.scala │ │ └── XYPlot.scala │ ├── operators/ │ │ ├── BinaryOp.scala │ │ ├── BinaryOpRegistry.scala │ │ ├── BinaryUpdateOp.scala │ │ ├── CanCast.scala │ │ ├── OpType.scala │ │ ├── Ops.scala │ │ ├── Shape.scala │ │ ├── TupleOps.scala │ │ ├── UnaryOp.scala │ │ ├── ValuesMonadic.scala │ │ ├── bundles/ │ │ │ └── VectorSpace.scala │ │ └── codegen/ │ │ ├── BinaryOpGenerator.scala │ │ ├── DynamicCompiler.scala │ │ └── GeneratedBinaryOp.scala │ ├── scalar/ │ │ ├── Complex.scala │ │ ├── RichScalar.scala │ │ ├── Scalar.scala │ │ ├── ScalarDecimal.scala │ │ └── package.scala │ └── tensor/ │ ├── CRSTensor2.scala │ ├── Counter.scala │ ├── Counter2.scala │ ├── DiagonalMatrix.scala │ ├── DomainFunction.scala │ ├── LiteralRow.scala │ ├── Matrix.scala │ ├── MatrixSingularException.scala │ ├── MatrixTranspose.scala │ ├── SelectAll.scala │ ├── Tensor.scala │ ├── Tensor1.scala │ ├── Tensor1Col.scala │ ├── Tensor1Proxy.scala │ ├── Tensor1Row.scala │ ├── Tensor1Slice.scala │ ├── Tensor2.scala │ ├── Tensor2Transpose.scala │ ├── TensorN.scala │ ├── TensorProxy.scala │ ├── TensorSlice.scala │ ├── TensorView.scala │ ├── Vector.scala │ ├── VectorCol.scala │ ├── VectorProxy.scala │ ├── VectorRow.scala │ ├── VectorSlice.scala │ ├── dense/ │ │ ├── ArrayArrayMatrix.scala │ │ ├── DenseArrayTensor.scala │ │ ├── DenseMatrix.scala │ │ └── DenseVector.scala │ ├── domain/ │ │ ├── CanBuildDomain2.scala │ │ ├── CanGetDomain.scala │ │ ├── Domain.scala │ │ ├── Domain1.scala │ │ ├── Domain2.scala │ │ ├── DomainN.scala │ │ ├── IndexDomain.scala │ │ ├── IterableDomain.scala │ │ ├── SetDomain.scala │ │ ├── TableDomain.scala │ │ └── UnionDomain.scala │ ├── generic/ │ │ ├── TensorBuilder.scala │ │ ├── TensorKeysMonadic.scala │ │ ├── TensorNonZeroKeysMonadic.scala │ │ ├── TensorNonZeroMonadic.scala │ │ ├── TensorNonZeroPairsMonadic.scala │ │ ├── TensorNonZeroTriplesMonadic.scala │ │ ├── TensorNonZeroValuesMonadic.scala │ │ ├── TensorPairsMonadic.scala │ │ ├── TensorTriplesMonadic.scala │ │ └── TensorValuesMonadic.scala │ ├── mutable/ │ │ ├── CRSTensor2.scala │ │ ├── Counter.scala │ │ ├── Counter2.scala │ │ ├── Matrix.scala │ │ ├── MatrixTranspose.scala │ │ ├── Tensor.scala │ │ ├── Tensor1.scala │ │ ├── Tensor1Col.scala │ │ ├── Tensor1Row.scala │ │ ├── Tensor1Slice.scala │ │ ├── Tensor2.scala │ │ ├── Tensor2Transpose.scala │ │ ├── TensorProxy.scala │ │ ├── TensorSlice.scala │ │ ├── Vector.scala │ │ ├── VectorCol.scala │ │ ├── VectorRow.scala │ │ └── VectorSlice.scala │ ├── package.scala │ └── sparse/ │ ├── SparseArrayTensor.scala │ └── SparseVector.scala └── test/ └── scala/ └── scalala/ ├── collection/ │ └── sparse/ │ └── SparseArrayTest.scala ├── generic/ │ ├── CanAssignIntoTest.scala │ └── collection/ │ ├── CanGetDoubleTest.scala │ ├── CanGetValueTest.scala │ └── CanMapValuesTest.scala ├── library/ │ ├── LibraryTest.scala │ ├── LinearAlgebraTest.scala │ ├── NumericsTest.scala │ ├── RandomTest.scala │ ├── StatisticsTest.scala │ └── StorageTest.scala ├── operators/ │ ├── ArrayTest.scala │ ├── SparseArrayTest.scala │ ├── TupleTest.scala │ └── bundles/ │ └── VectorSpaceTest.scala ├── scalar/ │ └── ComplexTest.scala └── tensor/ ├── CRSTensor2Test.scala ├── Counter2Test.scala ├── CounterTest.scala ├── DiagonalMatrixTest.scala ├── Tensor2Test.scala ├── TensorTest.scala ├── dense/ │ ├── DenseMatrixTest.scala │ ├── DenseVectorConstructorTest.scala │ └── DenseVectorTest.scala └── sparse/ └── SparseVectorTest.scala ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *~ .idea/ .idea_modules/ .manager/ workspace.xml bin/ docs/ target/ lib_managed/ src_managed/ project/boot/ project/plugins/project/ ================================================ FILE: LICENSE ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: README ================================================ Scalala is a high performance numeric linear algebra library for Scala, with rich Matlab-like operators on vectors and matrices; a library of numerical routines; support for plotting. This software is released under the LGPL. See LICENSE for details. (c) 2008- | Daniel Ramage | dramage | http://cs.stanford.edu/~dramage With contributions from: David Hall Jason Zaugg Alexander Lehmann Jonathan Merritt aerskine And others (email me if you've contributed code and aren't listed) Building upon and/or borrowing from solid libraries: JFreeChart http://www.jfree.org/jfreechart/ Netlib http://code.google.com/p/netlib-java/ MTJ http://code.google.com/p/matrix-toolkits-java/ iText http://www.itextpdf.com/ The source currently lives on github. You can download a copy: git clone https://github.com/scalala/Scalala.git Scalala is built with sbt, which is included in the repository or can be downloaded from https://github.com/harrah/xsbt/wiki. Run sbt (./sbt) and invoke one or more of the following targets: update -- Downloads scalala's dependencies compile -- Builds the library test -- Runs the unit tests doc -- Builds scaladoc for the public API proguard -- Builds a distributable jar gen-idea -- Generate an IntelliJ IDEA project For project maintainers, the project can be deployed with: publish To run an interactive console, either do so through sbt (console or console-quick) or run sbt's proguard target, and then: java -jar target/scala_2.8.1/scalala*.min.jar Documentation is available here: https://github.com/scalala/Scalala/wiki/Scalala And informal support is available here: http://groups.google.com/group/scalala ================================================ FILE: build.sbt ================================================ name := "scalala" version := "1.0.0.RC3-SNAPSHOT" organization := "org.scalala" scalaVersion := "2.9.2" crossScalaVersions := Seq("2.8.2", "2.9.1", "2.9.2") resolvers ++= Seq( "ScalaNLP Maven2" at "http://repo.scalanlp.org/repo", "Scala Tools Snapshots" at "http://scala-tools.org/repo-snapshots/" ) libraryDependencies ++= Seq( "com.googlecode.netlib-java" % "netlib-java" % "0.9.3", "jfree" % "jcommon" % "1.0.16", "jfree" % "jfreechart" % "1.0.13", "org.apache.xmlgraphics" % "xmlgraphics-commons" % "1.3.1", // for eps gen // "org.apache.xmlgraphics" % "batik-dom" % "1.7", // for svg gen // "org.apache.xmlgraphics" % "batik-svggen" % "1.7", // for svg gen "com.lowagie" % "itext" % "2.1.5" intransitive(), // for pdf gen "junit" % "junit" % "4.5" % "test" ) libraryDependencies <<= (scalaVersion, libraryDependencies) { (sv, deps) => deps :+ ("org.scala-lang" % "scala-compiler" % sv) } libraryDependencies <<= (scalaVersion, libraryDependencies) { (sv, deps) => val Scala210 = """2\.10\.0.*""".r sv match { case "2.9.1" | "2.9.2" | Scala210() => deps :+ ("jline" % "jline" % "0.9.94") // ("org.scala-lang" % "jline" % "2.9.1") case x if x.startsWith("2.8") => deps :+ ("jline" % "jline" % "0.9.94") case x => error("Unsupported Scala version " + x) } } libraryDependencies <<= (scalaVersion, libraryDependencies) { (sv, deps) => val Scala210 = """2\.10\.0.*""".r sv match { case Scala210() => deps case "2.9.1" | "2.9.2" => (deps :+ ("org.scalatest" % "scalatest" % "1.4.RC2" % "test") :+ ("org.scala-tools.testing" % "scalacheck_2.9.1" % "1.9" % "test")) case x if x.startsWith("2.8") => (deps :+ ("org.scalatest" % "scalatest" % "1.3" % "test") :+ ("org.scala-tools.testing" % "scalacheck_2.8.1" % "1.8" % "test")) case x => error("Unsupported Scala version " + x) } } publishTo <<= (version) { version: String => val nexus = "http://nexus.scala-tools.org/content/repositories/" if (version.trim.endsWith("SNAPSHOT")) Some("snapshots" at nexus + "snapshots/") else Some("releases" at nexus + "releases/") } credentials += Credentials(Path.userHome / ".ivy2" / ".credentials") javacOptions ++= Seq("-source", "1.5", "-target", "1.5") scalacOptions ++= Seq("-no-specialization","-deprecation","-target:jvm-1.5") initialCommands := scala.io.Source.fromFile("src/main/resources/scalala.scala").getLines.mkString("\n") mainClass in (Compile,packageBin) := Some("scalala.ScalalaConsole") javaOptions += "-Xmx2g" seq(ProguardPlugin.proguardSettings :_*) proguardOptions ++= Seq ( "-keep class scalala.** { *; }", "-keep class org.jfree.** { *; }", keepMain("scalala.ScalalaConsole$"), keepMain("scala.tools.nsc.MainGenericRunner"), "-dontoptimize", "-dontobfuscate", keepLimitedSerializability, keepAllScala, "-keep class ch.epfl.** { *; }", "-keep interface scala.ScalaObject" ) // seq(com.github.retronym.SbtOneJar.oneJarSettings: _*) ================================================ FILE: project/build.properties ================================================ sbt.version=0.11.3 ================================================ FILE: project/plugins.sbt ================================================ resolvers += "Proguard plugin repo" at "http://siasia.github.com/maven2" libraryDependencies <+= sbtVersion(v => "com.github.siasia" %% "xsbt-proguard-plugin" % ("0.11.2-0.1.1")) addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.0.0") ================================================ FILE: sbt ================================================ #!/usr/bin/env bash # # A more capable sbt runner, coincidentally also called sbt. # Author: Paul Phillips # todo - make this dynamic declare -r sbt_release_version=0.11.3 declare -r sbt_snapshot_version=0.13.0-SNAPSHOT unset sbt_jar sbt_dir sbt_create sbt_snapshot sbt_launch_dir unset scala_version java_home sbt_explicit_version unset verbose debug quiet build_props_sbt () { if [[ -f project/build.properties ]]; then versionLine=$(grep ^sbt.version project/build.properties) versionString=${versionLine##sbt.version=} echo "$versionString" fi } update_build_props_sbt () { local ver="$1" local old=$(build_props_sbt) if [[ $ver == $old ]]; then return elif [[ -f project/build.properties ]]; then perl -pi -e "s/^sbt\.version=.*\$/sbt.version=${ver}/" project/build.properties grep -q '^sbt.version=' project/build.properties || echo "sbt.version=${ver}" >> project/build.properties echo !!! echo !!! Updated file project/build.properties setting sbt.version to: $ver echo !!! Previous value was: $old echo !!! fi } sbt_version () { if [[ -n $sbt_explicit_version ]]; then echo $sbt_explicit_version else local v=$(build_props_sbt) if [[ -n $v ]]; then echo $v else echo $sbt_release_version fi fi } echoerr () { echo 1>&2 "$@" } vlog () { [[ $verbose || $debug ]] && echoerr "$@" } dlog () { [[ $debug ]] && echoerr "$@" } # this seems to cover the bases on OSX, and someone will # have to tell me about the others. get_script_path () { local path="$1" [[ -L "$path" ]] || { echo "$path" ; return; } local target=$(readlink "$path") if [[ "${target:0:1}" == "/" ]]; then echo "$target" else echo "$(dirname $path)/$target" fi } # a ham-fisted attempt to move some memory settings in concert # so they need not be dicked around with individually. get_mem_opts () { local mem=${1:-1536} local perm=$(( $mem / 4 )) (( $perm > 256 )) || perm=256 (( $perm < 1024 )) || perm=1024 local codecache=$(( $perm / 2 )) echo "-Xms${mem}m -Xmx${mem}m -XX:MaxPermSize=${perm}m -XX:ReservedCodeCacheSize=${codecache}m" } die() { echo "Aborting: $@" exit 1 } make_url () { groupid="$1" category="$2" version="$3" echo "http://typesafe.artifactoryonline.com/typesafe/ivy-$category/$groupid/sbt-launch/$version/sbt-launch.jar" } declare -r default_jvm_opts="-Dfile.encoding=UTF8" declare -r default_sbt_opts="-XX:+CMSClassUnloadingEnabled" declare -r default_sbt_mem=1536 declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" declare -r sbt_opts_file=".sbtopts" declare -r jvm_opts_file=".jvmopts" declare -r latest_28="2.8.2" declare -r latest_29="2.9.1" declare -r latest_210="2.10.0-SNAPSHOT" declare -r script_path=$(get_script_path "$BASH_SOURCE") declare -r script_dir="$(dirname $script_path)" declare -r script_name="$(basename $script_path)" # some non-read-onlies set with defaults declare java_cmd=java declare sbt_launch_dir="$script_dir/.lib" declare sbt_mem=$default_sbt_mem # pull -J and -D options to give to java. declare -a residual_args declare -a java_args declare -a scalac_args declare -a sbt_commands build_props_scala () { if [[ -f project/build.properties ]]; then versionLine=$(grep ^build.scala.versions project/build.properties) versionString=${versionLine##build.scala.versions=} echo ${versionString%% .*} fi } execRunner () { # print the arguments one to a line, quoting any containing spaces [[ $verbose || $debug ]] && echo "# Executing command line:" && { for arg; do if printf "%s\n" "$arg" | grep -q ' '; then printf "\"%s\"\n" "$arg" else printf "%s\n" "$arg" fi done echo "" } exec "$@" } sbt_groupid () { case $(sbt_version) in 0.7.*) echo org.scala-tools.sbt ;; 0.10.*) echo org.scala-tools.sbt ;; 0.11.[12]) echo org.scala-tools.sbt ;; *) echo org.scala-sbt ;; esac } sbt_artifactory_list () { local version0=$(sbt_version) local version=${version0%-SNAPSHOT} local url="http://typesafe.artifactoryonline.com/typesafe/ivy-snapshots/$(sbt_groupid)/sbt-launch/" dlog "Looking for snapshot list at: $url " curl -s --list-only "$url" | \ grep -F $version | \ perl -e 'print reverse <>' | \ perl -pe 's#^/dev/null dlog "curl returned: $?" echo "$url" return done } jar_url () { case $(sbt_version) in 0.7.*) echo "http://simple-build-tool.googlecode.com/files/sbt-launch-0.7.7.jar" ;; *-SNAPSHOT) make_snapshot_url ;; *) make_release_url ;; esac } jar_file () { echo "$sbt_launch_dir/$1/sbt-launch.jar" } download_url () { local url="$1" local jar="$2" echo "Downloading sbt launcher $(sbt_version):" echo " From $url" echo " To $jar" mkdir -p $(dirname "$jar") && { if which curl >/dev/null; then curl --fail --silent "$url" --output "$jar" elif which wget >/dev/null; then wget --quiet -O "$jar" "$url" fi } && [[ -f "$jar" ]] } acquire_sbt_jar () { sbt_url="$(jar_url)" sbt_jar="$(jar_file $(sbt_version))" [[ -f "$sbt_jar" ]] || download_url "$sbt_url" "$sbt_jar" } usage () { cat < path to global settings/plugins directory (default: ~/.sbt/) -sbt-boot path to shared boot directory (default: ~/.sbt/boot in 0.11 series) -ivy path to local Ivy repository (default: ~/.ivy2) -mem set memory options (default: $sbt_mem, which is $(get_mem_opts $sbt_mem) ) -no-share use all local caches; no sharing -offline put sbt in offline mode -jvm-debug Turn on JVM debugging, open at the given port. -batch Disable interactive mode # sbt version (default: from project/build.properties if present, else latest release) !!! The only way to accomplish this pre-0.12.0 if there is a build.properties file which !!! contains an sbt.version property is to update the file on disk. That's what this does. -sbt-version use the specified version of sbt -sbt-jar use the specified jar as the sbt launcher -sbt-snapshot use a snapshot version of sbt -sbt-launch-dir directory to hold sbt launchers (default: $sbt_launch_dir) # scala version (default: as chosen by sbt) -28 use $latest_28 -29 use $latest_29 -210 use $latest_210 -scala-home use the scala build at the specified directory -scala-version use the specified version of scala # java version (default: java from PATH, currently $(java -version |& grep version)) -java-home alternate JAVA_HOME # jvm options and output control JAVA_OPTS environment variable holding jvm args, if unset uses "$default_jvm_opts" SBT_OPTS environment variable holding jvm args, if unset uses "$default_sbt_opts" .jvmopts if file is in sbt root, it is prepended to the args given to the jvm .sbtopts if file is in sbt root, it is prepended to the args given to **sbt** -Dkey=val pass -Dkey=val directly to the jvm -J-X pass option -X directly to the jvm (-J is stripped) -S-X add -X to sbt's scalacOptions (-J is stripped) In the case of duplicated or conflicting options, the order above shows precedence: JAVA_OPTS lowest, command line options highest. EOM } addJava () { dlog "[addJava] arg = '$1'" java_args=( "${java_args[@]}" "$1" ) } addSbt () { dlog "[addSbt] arg = '$1'" sbt_commands=( "${sbt_commands[@]}" "$1" ) } addScalac () { dlog "[addScalac] arg = '$1'" scalac_args=( "${scalac_args[@]}" "$1" ) } addResidual () { dlog "[residual] arg = '$1'" residual_args=( "${residual_args[@]}" "$1" ) } addResolver () { addSbt "set resolvers in ThisBuild += $1" } addDebugger () { addJava "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1" } get_jvm_opts () { # echo "${JAVA_OPTS:-$default_jvm_opts}" # echo "${SBT_OPTS:-$default_sbt_opts}" [[ -f "$jvm_opts_file" ]] && cat "$jvm_opts_file" } process_args () { require_arg () { local type="$1" local opt="$2" local arg="$3" if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then die "$opt requires <$type> argument" fi } while [[ $# -gt 0 ]]; do case "$1" in -h|-help) usage; exit 1 ;; -v|-verbose) verbose=1 && shift ;; -d|-debug) debug=1 && shift ;; -q|-quiet) quiet=1 && shift ;; -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; -mem) require_arg integer "$1" "$2" && sbt_mem="$2" && shift 2 ;; -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; -no-share) addJava "$noshare_opts" && shift ;; -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;; -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; -offline) addSbt "set offline := true" && shift ;; -jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;; -batch) exec 0 )) || echo "Starting $script_name: invoke with -help for other options" # verify this is an sbt dir or -create was given [[ -f ./build.sbt || -d ./project || -n "$sbt_create" ]] || { cat <MersenneTwister and MersenneTwisterFast *

Version 13, based on version MT199937(99/10/29) * of the Mersenne Twister algorithm found at * * The Mersenne Twister Home Page, with the initialization * improved using the new 2002/1/26 initialization algorithm * By Sean Luke, October 2004. * *

MersenneTwister is a drop-in subclass replacement * for java.util.Random. It is properly synchronized and * can be used in a multithreaded environment. On modern VMs such * as HotSpot, it is approximately 1/3 slower than java.util.Random. * *

MersenneTwisterFast is not a subclass of java.util.Random. It has * the same public methods as Random does, however, and it is * algorithmically identical to MersenneTwister. MersenneTwisterFast * has hard-code inlined all of its methods directly, and made all of them * final (well, the ones of consequence anyway). Further, these * methods are not synchronized, so the same MersenneTwisterFast * instance cannot be shared by multiple threads. But all this helps * MersenneTwisterFast achieve well over twice the speed of MersenneTwister. * java.util.Random is about 1/3 slower than MersenneTwisterFast. * *

About the Mersenne Twister

*

This is a Java version of the C-program for MT19937: Integer version. * The MT19937 algorithm was created by Makoto Matsumoto and Takuji Nishimura, * who ask: "When you use this, send an email to: matumoto@math.keio.ac.jp * with an appropriate reference to your work". Indicate that this * is a translation of their algorithm into Java. * *

Reference. * Makato Matsumoto and Takuji Nishimura, * "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform * Pseudo-Random Number Generator", * ACM Transactions on Modeling and. Computer Simulation, * Vol. 8, No. 1, January 1998, pp 3--30. * *

About this Version

* *

Changes Since V12: clone() method added. * *

Changes Since V11: stateEquals(...) method added. MersenneTwisterFast * is equal to other MersenneTwisterFasts with identical state; likewise * MersenneTwister is equal to other MersenneTwister with identical state. * This isn't equals(...) because that requires a contract of immutability * to compare by value. * *

Changes Since V10: A documentation error suggested that * setSeed(int[]) required an int[] array 624 long. In fact, the array * can be any non-zero length. The new version also checks for this fact. * *

Changes Since V9: readState(stream) and writeState(stream) * provided. * *

Changes Since V8: setSeed(int) was only using the first 28 bits * of the seed; it should have been 32 bits. For small-number seeds the * behavior is identical. * *

Changes Since V7: A documentation error in MersenneTwisterFast * (but not MersenneTwister) stated that nextDouble selects uniformly from * the full-open interval [0,1]. It does not. nextDouble's contract is * identical across MersenneTwisterFast, MersenneTwister, and java.util.Random, * namely, selection in the half-open interval [0,1). That is, 1.0 should * not be returned. A similar contract exists in nextFloat. * *

Changes Since V6: License has changed from LGPL to BSD. * New timing information to compare against * java.util.Random. Recent versions of HotSpot have helped Random increase * in speed to the point where it is faster than MersenneTwister but slower * than MersenneTwisterFast (which should be the case, as it's a less complex * algorithm but is synchronized). * *

Changes Since V5: New empty constructor made to work the same * as java.util.Random -- namely, it seeds based on the current time in * milliseconds. * *

Changes Since V4: New initialization algorithms. See * (see * http://www.math.keio.ac.jp/matumoto/MT2002/emt19937ar.html) * *

The MersenneTwister code is based on standard MT19937 C/C++ * code by Takuji Nishimura, * with suggestions from Topher Cooper and Marc Rieffel, July 1997. * The code was originally translated into Java by Michael Lecuyer, * January 1999, and the original code is Copyright (c) 1999 by Michael Lecuyer. * *

Java notes

* *

This implementation implements the bug fixes made * in Java 1.2's version of Random, which means it can be used with * earlier versions of Java. See * * the JDK 1.2 java.util.Random documentation for further documentation * on the random-number generation contracts made. Additionally, there's * an undocumented bug in the JDK java.util.Random.nextBytes() method, * which this code fixes. * *

Just like java.util.Random, this * generator accepts a long seed but doesn't use all of it. java.util.Random * uses 48 bits. The Mersenne Twister instead uses 32 bits (int size). * So it's best if your seed does not exceed the int range. * *

MersenneTwister can be used reliably * on JDK version 1.1.5 or above. Earlier Java versions have serious bugs in * java.util.Random; only MersenneTwisterFast (and not MersenneTwister nor * java.util.Random) should be used with them. * *

License

* * Copyright (c) 2003 by Sean Luke.
* Portions copyright (c) 1993 by Michael Lecuyer.
* All rights reserved.
* *

Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: *

    *
  • Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. *
  • Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. *
  • Neither the name of the copyright owners, their employers, nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. *
*

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * @version 13 */ // Note: this class is hard-inlined in all of its methods. This makes some of // the methods well-nigh unreadable in their complexity. In fact, the Mersenne // Twister is fairly easy code to understand: if you're trying to get a handle // on the code, I strongly suggest looking at MersenneTwister.java first. // -- Sean public class MersenneTwisterFast implements Serializable, Cloneable { // Period parameters private static final int N = 624; private static final int M = 397; private static final int MATRIX_A = 0x9908b0df; // private static final * constant vector a private static final int UPPER_MASK = 0x80000000; // most significant w-r bits private static final int LOWER_MASK = 0x7fffffff; // least significant r bits // Tempering parameters private static final int TEMPERING_MASK_B = 0x9d2c5680; private static final int TEMPERING_MASK_C = 0xefc60000; private int mt[]; // the array for the state vector private int mti; // mti==N+1 means mt[N] is not initialized private int mag01[]; // a good initial seed (of int size, though stored in a long) //private static final long GOOD_SEED = 4357; private double __nextNextGaussian; private boolean __haveNextNextGaussian; /* We're overriding all internal data, to my knowledge, so this should be okay */ public Object clone() throws CloneNotSupportedException { MersenneTwisterFast f = (MersenneTwisterFast)(super.clone()); f.mt = (int[])(mt.clone()); f.mag01 = (int[])(mag01.clone()); return f; } public boolean stateEquals(Object o) { if (o==this) return true; if (o == null || !(o instanceof MersenneTwisterFast)) return false; MersenneTwisterFast other = (MersenneTwisterFast) o; if (mti != other.mti) return false; for(int x=0;x>> 30)) + mti); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ mt[mti] &= 0xffffffff; /* for >32 bit machines */ } } /** * Sets the seed of the MersenneTwister using an array of integers. * Your array must have a non-zero length. Only the first 624 integers * in the array are used; if the array is shorter than this then * integers are repeatedly used in a wrap-around fashion. */ synchronized public void setSeed(final int[] array) { if (array.length == 0) throw new IllegalArgumentException("Array length must be greater than zero"); int i, j, k; setSeed(19650218); i=1; j=0; k = (N>array.length ? N : array.length); for (; k!=0; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 30)) * 1664525)) + array[j] + j; /* non linear */ mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */ i++; j++; if (i>=N) { mt[0] = mt[N-1]; i=1; } if (j>=array.length) j=0; } for (k=N-1; k!=0; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 30)) * 1566083941)) - i; /* non linear */ mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */ i++; if (i>=N) { mt[0] = mt[N-1]; i=1; } } mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */ } public final int nextInt() { int y; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) return y; } public final short nextShort() { int y; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) return (short)(y >>> 16); } public final char nextChar() { int y; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) return (char)(y >>> 16); } public final boolean nextBoolean() { int y; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) return (boolean)((y >>> 31) != 0); } /** This generates a coin flip with a probability probability of returning true, else returning false. probability must be between 0.0 and 1.0, inclusive. Not as precise a random real event as nextBoolean(double), but twice as fast. To explicitly use this, remember you may need to cast to float first. */ public final boolean nextBoolean(final float probability) { int y; if (probability < 0.0f || probability > 1.0f) throw new IllegalArgumentException ("probability must be between 0.0 and 1.0 inclusive."); if (probability==0.0f) return false; // fix half-open issues else if (probability==1.0f) return true; // fix half-open issues if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) return (y >>> 8) / ((float)(1 << 24)) < probability; } /** This generates a coin flip with a probability probability of returning true, else returning false. probability must be between 0.0 and 1.0, inclusive. */ public final boolean nextBoolean(final double probability) { int y; int z; if (probability < 0.0 || probability > 1.0) throw new IllegalArgumentException ("probability must be between 0.0 and 1.0 inclusive."); if (probability==0.0) return false; // fix half-open issues else if (probability==1.0) return true; // fix half-open issues if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (z >>> 1) ^ mag01[z & 0x1]; } for (; kk < N-1; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (z >>> 1) ^ mag01[z & 0x1]; } z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1]; mti = 0; } z = mt[mti++]; z ^= z >>> 11; // TEMPERING_SHIFT_U(z) z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z) z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z) z ^= (z >>> 18); // TEMPERING_SHIFT_L(z) /* derived from nextDouble documentation in jdk 1.2 docs, see top */ return ((((long)(y >>> 6)) << 27) + (z >>> 5)) / (double)(1L << 53) < probability; } public final byte nextByte() { int y; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) return (byte)(y >>> 24); } public final void nextBytes(byte[] bytes) { int y; for (int x=0;x= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) bytes[x] = (byte)(y >>> 24); } } public final long nextLong() { int y; int z; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (z >>> 1) ^ mag01[z & 0x1]; } for (; kk < N-1; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (z >>> 1) ^ mag01[z & 0x1]; } z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1]; mti = 0; } z = mt[mti++]; z ^= z >>> 11; // TEMPERING_SHIFT_U(z) z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z) z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z) z ^= (z >>> 18); // TEMPERING_SHIFT_L(z) return (((long)y) << 32) + (long)z; } /** Returns a long drawn uniformly from 0 to n-1. Suffice it to say, n must be > 0, or an IllegalArgumentException is raised. */ public final long nextLong(final long n) { if (n<=0) throw new IllegalArgumentException("n must be > 0"); long bits, val; do { int y; int z; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (z >>> 1) ^ mag01[z & 0x1]; } for (; kk < N-1; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (z >>> 1) ^ mag01[z & 0x1]; } z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1]; mti = 0; } z = mt[mti++]; z ^= z >>> 11; // TEMPERING_SHIFT_U(z) z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z) z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z) z ^= (z >>> 18); // TEMPERING_SHIFT_L(z) bits = (((((long)y) << 32) + (long)z) >>> 1); val = bits % n; } while (bits - val + (n-1) < 0); return val; } /** Returns a random double in the half-open range from [0.0,1.0). Thus 0.0 is a valid result but 1.0 is not. */ public final double nextDouble() { int y; int z; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (z >>> 1) ^ mag01[z & 0x1]; } for (; kk < N-1; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (z >>> 1) ^ mag01[z & 0x1]; } z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1]; mti = 0; } z = mt[mti++]; z ^= z >>> 11; // TEMPERING_SHIFT_U(z) z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z) z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z) z ^= (z >>> 18); // TEMPERING_SHIFT_L(z) /* derived from nextDouble documentation in jdk 1.2 docs, see top */ return ((((long)(y >>> 6)) << 27) + (z >>> 5)) / (double)(1L << 53); } public final double nextGaussian() { if (__haveNextNextGaussian) { __haveNextNextGaussian = false; return __nextNextGaussian; } else { double v1, v2, s; do { int y; int z; int a; int b; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (z >>> 1) ^ mag01[z & 0x1]; } for (; kk < N-1; kk++) { z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (z >>> 1) ^ mag01[z & 0x1]; } z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1]; mti = 0; } z = mt[mti++]; z ^= z >>> 11; // TEMPERING_SHIFT_U(z) z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z) z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z) z ^= (z >>> 18); // TEMPERING_SHIFT_L(z) if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { a = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (a >>> 1) ^ mag01[a & 0x1]; } for (; kk < N-1; kk++) { a = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (a >>> 1) ^ mag01[a & 0x1]; } a = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (a >>> 1) ^ mag01[a & 0x1]; mti = 0; } a = mt[mti++]; a ^= a >>> 11; // TEMPERING_SHIFT_U(a) a ^= (a << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(a) a ^= (a << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(a) a ^= (a >>> 18); // TEMPERING_SHIFT_L(a) if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { b = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (b >>> 1) ^ mag01[b & 0x1]; } for (; kk < N-1; kk++) { b = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (b >>> 1) ^ mag01[b & 0x1]; } b = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (b >>> 1) ^ mag01[b & 0x1]; mti = 0; } b = mt[mti++]; b ^= b >>> 11; // TEMPERING_SHIFT_U(b) b ^= (b << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(b) b ^= (b << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(b) b ^= (b >>> 18); // TEMPERING_SHIFT_L(b) /* derived from nextDouble documentation in jdk 1.2 docs, see top */ v1 = 2 * (((((long)(y >>> 6)) << 27) + (z >>> 5)) / (double)(1L << 53)) - 1; v2 = 2 * (((((long)(a >>> 6)) << 27) + (b >>> 5)) / (double)(1L << 53)) - 1; s = v1 * v1 + v2 * v2; } while (s >= 1 || s==0); double multiplier = /*Strict*/Math.sqrt(-2 * /*Strict*/Math.log(s)/s); __nextNextGaussian = v2 * multiplier; __haveNextNextGaussian = true; return v1 * multiplier; } } /** Returns a random float in the half-open range from [0.0f,1.0f). Thus 0.0f is a valid result but 1.0f is not. */ public final float nextFloat() { int y; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) return (y >>> 8) / ((float)(1 << 24)); } /** Returns an integer drawn uniformly from 0 to n-1. Suffice it to say, n must be > 0, or an IllegalArgumentException is raised. */ public final int nextInt(final int n) { if (n<=0) throw new IllegalArgumentException("n must be > 0"); if ((n & -n) == n) // i.e., n is a power of 2 { int y; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) return (int)((n * (long) (y >>> 1) ) >> 31); } int bits, val; do { int y; if (mti >= N) // generate N words at one time { int kk; final int[] mt = this.mt; // locals are slightly faster final int[] mag01 = this.mag01; // locals are slightly faster for (kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= y >>> 11; // TEMPERING_SHIFT_U(y) y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y) y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y) y ^= (y >>> 18); // TEMPERING_SHIFT_L(y) bits = (y >>> 1); val = bits % n; } while(bits - val + (n-1) < 0); return val; } } ================================================ FILE: src/main/resources/scalala.scala ================================================ import scalala.scalar._; import scalala.tensor.::; import scalala.tensor.mutable._; import scalala.tensor.dense._; import scalala.tensor.sparse._; import scalala.library.Library._; import scalala.library.LinearAlgebra._; import scalala.library.Statistics._; import scalala.library.Plotting._; import scalala.operators.Implicits._; ================================================ FILE: src/main/scala/scalala/ScalalaConsole.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; /** * Runs Scalala in a console. * * @author dlwh,dramage */ object ScalalaConsole { def main(args : Array[String]) { // read scalala.scala to a tmp file val stream = this.getClass.getClassLoader.getResourceAsStream("scalala.scala"); val file = java.io.File.createTempFile("scalala-startup-", ".scala"); file.deleteOnExit; val fos = new java.io.PrintStream(new java.io.FileOutputStream(file)); for (line <- scala.io.Source.fromInputStream(stream).getLines()) { fos.println(line); } fos.close(); // redirect to invoking the standard scala main method val method = Class.forName("scala.tools.nsc.MainGenericRunner"). getMethod("main", classOf[Array[String]]); // augmented arguments val aurg : Object = ( List[String]( "-nocompdaemon", "-classpath", System.getProperty("java.class.path"), "-no-specialization", "-Yrepl-sync", "-usejavacp", "-i", file.getAbsolutePath ) ++ args ).toArray[String]; method.invoke(null, aurg); } /** The width of the console, or 80 if it can't be discovered. */ lazy val terminalWidth : Int = { // this ugly try-catch is here to use scala's built-in jline, // which only exists in scala > 2.9 try { type Terminal = { def getWidth() : Int; def getHeight() : Int; } val terminal = Class.forName("scala.tools.jline.TerminalFactory"). getMethod("create").invoke(null).asInstanceOf[Terminal]; terminal.getWidth() } catch { case _ => try { type Terminal = { def getTerminalWidth() : Int; def getTerminalHeight() : Int; } val terminal = Class.forName("jline.Terminal"). getMethod("getInstance").invoke(null).asInstanceOf[Terminal]; terminal.getTerminalWidth() } catch { case _ => 80 } } }; /** The height of the console, or 24 if it can't be discovered. */ lazy val terminalHeight : Int = { // this ugly try-catch is here to use scala's built-in jline, // which only exists in scala > 2.9 try { type Terminal = { def getWidth() : Int; def getHeight() : Int; } val terminal = Class.forName("scala.tools.jline.TerminalFactory"). getMethod("create").invoke(null).asInstanceOf[Terminal]; terminal.getHeight(); } catch { case _ => try { type Terminal = { def getTerminalWidth() : Int; def getTerminalHeight() : Int; } val terminal = Class.forName("jline.Terminal"). getMethod("getInstance").invoke(null).asInstanceOf[Terminal]; terminal.getTerminalHeight() } catch { case _ => 24 } } }; } ================================================ FILE: src/main/scala/scalala/collection/sparse/SparseArray.scala ================================================ /* Copyright 2009 David Hall, Daniel Ramage 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. */ package scalala.collection.sparse; import scala.collection.generic._; import scala.collection.mutable._; import scalala.operators._; import scalala.scalar.Scalar import java.util.Arrays ; /** *

Nearly-drop-in replacement for Array[T](length) that does not store * default array values. Internally, the SparseArray data structure * stores an array of indexes in packed, sorted order, and a * corresponding packed array of values. Updates are linear in * the number of non-zero array elements, while accesses are * logarithmic. This class is not threadsafe for simultaneous * reads and writes, but more than one thread can read simultaneously * if no threads are writing.

* *

Note that the DefaultArrayValue must be a constant reference -- no * clever tricks like creating new instances of type T are supported * by the nature of the way this map works. Otherwise, iterating * over the size of the array would cause the SparseArray to become * (inefficiently) dense.

* * @param length The virtual length of the array. * @param index The indices of the array, in packed sorted order. * @param data The data of the array, in corresponding positions to index. * @param used The number of used elements in index and data. * @param initialActiveLength The initial length of the sparse data structures * when creating new instances. * * @author dlwh, dramage */ @SerialVersionUID(1L) final class SparseArray[@specialized T] (val length : Int, protected var index : Array[Int], protected var data : Array[T], protected var used : Int, initialActiveLength : Int) (implicit m : ClassManifest[T], df : DefaultArrayValue[T]) extends Serializable { def copy: SparseArray[T] = { val newData = m.newArray(data.length) Array.copy(data,0,newData,0,data.length) new SparseArray(length, Arrays.copyOf(index, index.length), newData, used, initialActiveLength) } def this(length : Int, initialActiveLength : Int = 3)(implicit m : ClassManifest[T], d : DefaultArrayValue[T]) = this(length, new Array[Int](initialActiveLength), new Array[T](initialActiveLength), 0, initialActiveLength)(m, d); checkInvariants() private def checkInvariants() { // check rep invariants require(length >= 0, "Length must be non-negative"); require(used >= 0 && used <= length, "Used must be <= length and >= 0"); if (used > 0) { require(index(0) >= 0, "Indexes must be ordered and non-negative"); var i = 1; while (i < used) { require(index(i-1) < index(i) && index(i) >= 0, "Indexes must be ordered and non-negative"); i +=1; } } } /** Default value. */ val default = df.value; /** Iterator over used indexes and values */ def iterator = Iterator.range(0, used).map(i => (index(i),data(i))); /** Used indexes. */ def indexIterator = index.iterator.take(used); /** Used values. */ def valueIterator = data.iterator.take(used); /** Key value pairs of non-default entries. */ def activeIterator = indexIterator zip valueIterator; /** A copy of the keys in this array. */ def indexArray : Array[Int] = index.take(used); /** A copy of the values in this array. */ def valueArray : Array[T] = data.take(used); /** Raw access to the underlying data array. Use with caution */ def rawValueArray : Array[T] = data /** * Returns the offset into index and data for the requested vector * index. If the requested index is not found, the return value is * negative and can be converted into an insertion point with ~rv. */ private def findOffset(i : Int) : Int = { if (i < 0 || i >= length) throw new IndexOutOfBoundsException("Index "+i+" out of bounds [0,"+used+")"); if (used == 0) { // empty list; do nothing return -1; } else if (i > index(used-1)) { // special case for end of list - this is a big win for growing sparse arrays return ~used; } else { // regular binary search from begin to end (inclusive) var begin = 0; var end = used - 1; // Simple optimization: position i can't be after offset i. if(end > i) end = i; var mid = (end + begin) >> 1; while (begin <= end) { mid = (end + begin) >> 1; if (index(mid) < i) begin = mid + 1; else if (index(mid) > i) end = mid - 1; else return mid; } // no match found, return insertion point if (i <= index(mid)) return ~mid; // Insert here (before mid) else return ~(mid + 1); // Insert after mid } } def apply(i : Int) : T = { val offset = findOffset(i); if (offset >= 0) data(offset) else default; } def get(i: Int) : Option[T] = { val offset = findOffset(i); if (offset >= 0) Some(data(offset)) else None; } def getOrElse(i : Int, value : =>T) : T = { val offset = findOffset(i); if (offset >= 0) data(offset) else value; } def getOrElseUpdate(i : Int, value : =>T) : T = { val offset = findOffset(i); if (offset >= 0) data(offset) else { val v = value; update(i,v) v; } } /** Returns the size of the array. */ def activeLength = used; /** Returns the index of the item stored at the given offset. */ def indexAt(offset : Int) : Int = { if (offset >= used) throw new ArrayIndexOutOfBoundsException(); index(offset); } /** Returns the value of the item stored at the given offset. */ def valueAt(offset : Int) : T = { if (offset >= used) throw new ArrayIndexOutOfBoundsException(); data(offset); } /** * Sets the given value at the given index if the value is not * equal to the current default. The data and * index arrays will be grown to support the insertion if * necessary. The growth schedule doubles the amount * of allocated memory at each allocation request up until * the sparse array contains 1024 values, at which point * the growth is additive: an additional n * 1024 spaces will * be allocated for n in 1,2,4,8,16. The largest amount of * space added to this vector will be an additional 16*1024*(sizeof(T)+4), * which is 196608 bytes at a time for a SparseVector[Double], * although more space is needed temporarily while moving to the * new arrays. */ def update(i : Int, value : T) = { val offset = findOffset(i); if (offset >= 0) { // found at offset data(offset) = value; } else if (value != default) { // need to insert at ~offset val insertPos = ~offset; used += 1; if (used > data.length) { // need to grow array val newLength = { if (data.length == 0) { 4 } else if (data.length < 0x0400) { data.length * 2 } else if (data.length < 0x0800) { data.length + 0x0400 } else if (data.length < 0x1000) { data.length + 0x0800 } else if (data.length < 0x2000) { data.length + 0x1000 } else if (data.length < 0x4000) { data.length + 0x2000 } else { data.length + 0x4000 }; }; // allocate new arrays val newIndex = new Array[Int](newLength); val newData = new Array[T](newLength); // copy existing data into new arrays System.arraycopy(index, 0, newIndex, 0, insertPos); System.arraycopy(data, 0, newData, 0, insertPos); System.arraycopy(index, insertPos, newIndex, insertPos + 1, used - insertPos - 1); System.arraycopy(data, insertPos, newData, insertPos + 1, used - insertPos - 1); // update pointers index = newIndex; data = newData; } else if (used - insertPos > 1) { // need to make room for new element mid-array System.arraycopy(index, insertPos, index, insertPos + 1, used - insertPos - 1); System.arraycopy(data, insertPos, data, insertPos + 1, used - insertPos - 1); } // assign new value index(insertPos) = i; data(insertPos) = value; } } /** Clears this array, resetting to the initial size. */ def clear() { use(new Array[Int](initialActiveLength), new Array[T](initialActiveLength), 0); } /** Pre-allocate space in this array for all active indexes in other. */ def reserve[O](other : SparseArray[O]) { val rv = new SparseArray[T](this.length, this.used + other.used); var i = 0; var j = 0; while (j < other.used) { val indexI = index(i); val indexJ = index(j); while (i < used && indexI < indexJ) { rv(indexI) = data(i); i += 1; } rv(indexJ) = this(indexJ); j += 1; } while (i < used) { rv(index(i)) = data(i); i += 1; } use(rv.index, rv.data, rv.used); } /** Compacts the array by removing all stored default values. */ def compact() { val nz = { // number of non-zeros var _nz = 0; var i = 0; while (i < used) { if (data(i) != default) { _nz += 1; } i += 1; } _nz; } val newData = new Array[T](nz); val newIndex = new Array[Int](nz); var i = 0; var o = 0; while (i < used) { if (data(i) != default) { newData(o) = data(i); newIndex(o) = index(i); o += 1; } i += 1; } use(newIndex, newData, nz); } /** Use the given index and data arrays, of which the first inUsed are valid. */ private def use(inIndex : Array[Int], inData : Array[T], inUsed : Int) = { // no need to rep-check since method is private and all callers satisfy // these invariants. data = inData; index = inIndex; used = inUsed; } /** Sets this array to be a copy of the given other array. */ def set(that : SparseArray[T]) = { if (this.length != that.length) { throw new IllegalArgumentException("SparseArrays must be the same length"); } use(that.index.clone, that.data.clone, that.used); } private def checkrep() { if (index == null || data == null) throw new IllegalArgumentException("Index and data must be non-null"); if (index.length != data.length) throw new IllegalArgumentException("Index and data sizes do not match"); if (index.length < used) throw new IllegalArgumentException("Used is greater than provided array"); if (index(0) < 0 || index(0) >= used) throw new IllegalArgumentException("use inIndex out of range contains illegal offset @ 0"); var i = 1; while (i < used) { if (index(i) < 0 || index(i) >= used || index(i) < index(i-1)) throw new IllegalArgumentException("use inIndex out of range contains illegal offset @ "+i); i += 1; } } /** * Maps all values. If f(this.default) is not equal to the new default * value, the result may be an efficiently dense (or almost dense) paired * array. */ def map[B:ClassManifest:DefaultArrayValue](f : T=>B) : SparseArray[B] = { val newDefault = implicitly[DefaultArrayValue[B]].value; if (used < length && f(default) == newDefault) { // some default values but f(default) is still default val newIndex = new Array[Int](used); val newData = new Array[B](used); var i = 0; var o = 0; while (i < used) { newIndex(o) = index(i); val newValue = f(data(i)); if (newValue != newDefault) { newData(o) = newValue; o += 1; } i += 1; } new SparseArray[B](length, newIndex, newData, o, initialActiveLength); } else { // no default values stored or f(default) is non-default val newDefault = f(default); val newIndex = new Array[Int](length); val newData = new Array[B](length); var i = 0; var o = 0; while (i < used) { while (o < index(i)) { newIndex(o) = o; newData(o) = newDefault; o += 1; } newIndex(o) = o; newData(o) = f(data(i)); o += 1; i += 1; } while (o < length) { newIndex(o) = o; newData(o) = newDefault; o += 1; } val rv = new SparseArray[B](length, newIndex, newData, length, initialActiveLength); rv.compact; rv; } } /** * Filter's the array by removing all values for which f is false. */ def filter(f : T=>Boolean) : SparseArray[T] = { val newIndex = new Array[Int](used); val newData = new Array[T](used); var i = 0; var o = 0; while (i < used) { if (f(data(i))) { newIndex(o) = index(i) - (i - o); newData(o) = data(i); o += 1; } i += 1; } if (f(default)) { // if default values are accepted, assume we're full length. var newLength = length - (i - o); // ... and subtract from that length how many defined tail elements // were filtered ... var ii = used - 1; while (ii >= 0 && index(ii) > newIndex(o) && index(ii) == newLength - 1) { ii -= 1; newLength -= 1; } new SparseArray[T](newLength, newIndex, newData, o, initialActiveLength); } else { // if default values are not accepted, return a "dense" array by // setting each position in newIndex consecutively to forget missing // values val newLength = o; new SparseArray[T](newLength, Array.range(0,newLength), newData.take(newLength), newLength, initialActiveLength); } } /** * Tranforms all elements this array by applying the given function. If * f(default) == default, then only updates non-default values. Otherwise, * the map essentially becomes dense -- not so efficient an operation! */ def transform(f : T=>T) = { val newDefault = f(default); if (newDefault == default) { var i = 0; while (i < used) { data(i) = f(data(i)); i += 1; } } else { val newIndex = Array.range(0, length); val newData = new Array[T](length); var i = 0; var o = 0; while (i < used) { while (o < index(i)) { newData(o) = newDefault; o += 1; } newData(o) = f(data(i)); o += 1; i += 1; } while (o < length) { newData(o) = newDefault; o += 1; } use(newIndex, newData, length); } } /** Applies the given function to each non-default element. */ def foreachActivePair[U](f: ((Int,T) => U)) { var i = 0; while(i < used) { f(index(i), data(i)); i += 1; } } /** Applies the given function to each non-default element. */ def foreachActiveValue[U](f: T => U) { var i = 0; while(i < used) { f(data(i)); i += 1; } } /** Applies the given function to each non-default element. */ def foreachActiveKey[U](f: Int => U) { var i = 0; while(i < used) { f(index(i)); i += 1; } } def toArray = Array.tabulate(length)(apply); def toList = List.tabulate(length)(apply); def toIndexedSeq = List.tabulate(length)(apply); def toMap = (indexIterator zip valueIterator).toMap; override def hashCode = { var rv = 0; var i = 0; while (i < used) { if (data(i) != default) { rv += 17*rv + data(i).hashCode*7 + index(i); } i += 1; } rv; } override def equals(other : Any) : Boolean = other match { case that : SparseArray[_] => var thisI = 0; var thatI = 0; while (thisI < this.used && thatI < that.used) { if (this.index(thisI) < that.index(thatI)) { if (this.data(thisI) != that.default) return false; thisI += 1; } else if (that.index(thatI) < this.index(thisI)) { if (that.data(thatI) != this.default) return false; thatI += 1; } else { // this.index(thisI) == that.index(thatI) if (this.data(thisI) != that.data(thatI)) return false; thisI += 1; thatI += 1; } } while (thisI < this.used) { if (this.data(thisI) != that.default) return false; thisI += 1; } while (thatI < that.used) { if (that.data(thatI) != this.default) return false; thatI += 1; } true; case _ => false; } } object SparseArray extends SparseArrayOps { def apply[@specialized T:ClassManifest:DefaultArrayValue](values : T*) = { val rv = new SparseArray[T](values.length); var i = 0; for (v <- values) { rv(i) = v; i += 1; } rv.compact; rv; } /** * Creates a SparseArray filled with the given value. The value function * is called once initially to test if the returned value is equal to the * DefaultArrayValue - if so, an empty SparseArray with initialActiveLength * non-zero entries is returned. Otherwise, an inefficient "dense" * SparseArray is returned. * * @author dramage */ def fill[@specialized T:ClassManifest:DefaultArrayValue](length : Int, initialActiveLength : Int = 3)(value : =>T) : SparseArray[T] = { if (value != implicitly[DefaultArrayValue[T]].value) { val rv = new SparseArray[T](length = length, initialActiveLength = length); var i = 0; while (i < length) { rv(i) = value; i += 1; } rv; } else { new SparseArray[T](length = length, initialActiveLength = length); } } def create[@specialized T:ClassManifest:DefaultArrayValue](length : Int)(values : (Int,T)*) = { val rv = new SparseArray[T](length = length, initialActiveLength = values.length); for ((k,v) <- values) { rv(k) = v; } rv; } def tabulate[@specialized T:ClassManifest:DefaultArrayValue](length : Int, initialActiveLength : Int = 3)(fn : (Int => T)) = { val rv = new SparseArray[T](length = length, initialActiveLength = initialActiveLength); var i = 0; while (i < length) { val v = fn(i); if (v != rv.default) { rv(i) = v; } i += 1; } rv.compact; rv; } class RichSparseArray[V](override val repr : SparseArray[V]) extends MutableNumericOps[SparseArray[V]]; implicit def richSparseArray[V](repr : SparseArray[V]) = new RichSparseArray(repr); } trait LowerPrioritySparseArrayOps { /** Set sparse array with corresponding values from another array. */ implicit def OpSetSparseArraySparseArrayCast[V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[SparseArray[V1],SparseArray[V2],OpSet] = new BinaryUpdateOp[SparseArray[V1],SparseArray[V2],OpSet] { def opType = OpSet; def apply(a : SparseArray[V1], b : SparseArray[V2]) = { var i = 0; while (i < a.length) { a(i) = cast(b(i)); i += 1; } } } /** Set sparse array with casted corresponding values from another array. */ implicit def OpSetSparseArrayArrayCast[V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[SparseArray[V1],Array[V2],OpSet] = new BinaryUpdateOp[SparseArray[V1],Array[V2],OpSet] { def opType = OpSet; def apply(a : SparseArray[V1], b : Array[V2]) = { var i = 0; while (i < a.length) { a(i) = cast(b(i)); i += 1; } } } /** Set array to casted scalar. */ implicit def OpSetSparseArrayScalarCast[V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[SparseArray[V1],V2,OpSet] = new BinaryUpdateOp[SparseArray[V1],V2,OpSet] { def opType = OpSet; def apply(a : SparseArray[V1], b : V2) = { val v = cast(b); var i = 0; while (i < a.length) { a(i) = v; i += 1; } } } } trait LowPrioritySparseArrayOps { /** Update sparse array with corresponding values from another sparse array. */ implicit def OpUpdateSparseArraySparseArray[V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[SparseArray[V1], SparseArray[V2], O] = new BinaryUpdateOp[SparseArray[V1], SparseArray[V2], O] { def opType = op.opType; def apply(a : SparseArray[V1], b : SparseArray[V2]) = { require(a.length == b.length, "Inputs must be the same length"); var i = 0; while (i < a.length) { a(i) = op(a(i),b(i)); i += 1; } } } /** Set array with corresponding values from another array. */ implicit def OpSetSparseArraySparseArray[V](implicit s : Scalar[V]) : BinaryUpdateOp[SparseArray[V],SparseArray[V],OpSet] = new BinaryUpdateOp[SparseArray[V],SparseArray[V],OpSet] { def opType = OpSet; def apply(a : SparseArray[V], b : SparseArray[V]) = { require(a.length == b.length, "Inputs must be the same length"); var i = 0; while (i < a.length) { a(i) = b(i); i += 1; } } } /** Update sparse array with corresponding values from another array. */ implicit def OpUpdateSparseArrayArray[V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[SparseArray[V1], Array[V2], O] = new BinaryUpdateOp[SparseArray[V1], Array[V2], O] { def opType = op.opType; def apply(a : SparseArray[V1], b : Array[V2]) = { require(a.length == b.length, "Inputs must be the same length"); var i = 0; while (i < a.length) { a(i) = op(a(i),b(i)); i += 1; } } } /** Set sparse array with corresponding values from another array. */ implicit def OpSetSparseArrayArray[V](implicit s : Scalar[V]) : BinaryUpdateOp[SparseArray[V],Array[V],OpSet] = new BinaryUpdateOp[SparseArray[V],Array[V],OpSet] { def opType = OpSet; def apply(a : SparseArray[V], b : Array[V]) = { require(a.length == b.length, "Inputs must be the same length"); var i = 0; while (i < a.length) { a(i) = b(i); i += 1; } } } /** Update sparse array with scalar. */ implicit def OpUpdateSparseArrayScalar[V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], s : Scalar[V2]) : BinaryUpdateOp[SparseArray[V1], V2, O] = new BinaryUpdateOp[SparseArray[V1], V2, O] { def opType = op.opType; def apply(a : SparseArray[V1], b : V2) = { var i = 0; while (i < a.length) { a(i) = op(a(i),b); i += 1; } } } /** Set sparse array with scalar. */ implicit def OpSetSparseArrayScalar[V](implicit s : Scalar[V], dv : DefaultArrayValue[V]) : BinaryUpdateOp[SparseArray[V],V,OpSet] = new BinaryUpdateOp[SparseArray[V],V,OpSet] { def opType = OpSet; def apply(a : SparseArray[V], b : V) = { if (b == dv.value) { a.clear(); } else { var i = 0; while (i < a.length) { a(i) = b; i += 1; } } } } } trait SparseArrayOps extends LowPrioritySparseArrayOps { // // UnaryOps // implicit def UnaryOp[V,RV,O<:OpType] (implicit op : UnaryOp[V,O,RV], dv : DefaultArrayValue[RV], mf : Manifest[RV]) : UnaryOp[SparseArray[V],O,SparseArray[RV]] = new UnaryOp[SparseArray[V],O,SparseArray[RV]] { def opType = op.opType; def apply(a : SparseArray[V]) = a.map(op apply _); } // // BinaryOps // implicit def BinaryOpSparseArrayScalar[V1,V2,RV,O<:OpType] (implicit op : BinaryOp[V1,V2,O,RV], s : Scalar[V2], dv : DefaultArrayValue[RV], cm : ClassManifest[RV]) : BinaryOp[SparseArray[V1], V2, O, SparseArray[RV]] = new BinaryOp[SparseArray[V1], V2, O, SparseArray[RV]] { def opType = op.opType; def apply(a : SparseArray[V1], b : V2) = a.map(v => op(v, b)); } implicit def BinaryOpScalarSparseArray[V1,V2,RV,O<:OpType] (implicit op : BinaryOp[V1,V2,O,RV], s : Scalar[V1], dv : DefaultArrayValue[RV], cm : ClassManifest[RV]) : BinaryOp[V1, SparseArray[V2], O, SparseArray[RV]] = new BinaryOp[V1, SparseArray[V2], O, SparseArray[RV]] { def opType = op.opType; def apply(a : V1, b : SparseArray[V2]) = b.map(v => op(a, v)); } implicit def BinaryOpSparseArraySparseArray[V1,V2,RV,O<:OpType] (implicit op : BinaryOp[V1,V2,O,RV], c : CompatibleShape[V1,V2], dv : DefaultArrayValue[RV], cm : ClassManifest[RV]) : BinaryOp[SparseArray[V1],SparseArray[V2],O,SparseArray[RV]] = new BinaryOp[SparseArray[V1],SparseArray[V2],O,SparseArray[RV]] { def opType = op.opType; def apply(a : SparseArray[V1], b : SparseArray[V2]) = { // TODO: optimize if (try { op(a.default, b.default) == dv.value } catch { case _ => false; }) { outer(a, b); } else { all(a, b); } } /** Where both a and b have non-default values. */ def inner(a : SparseArray[V1], b : SparseArray[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new SparseArray[RV](a.length); var aO = 0; var bO = 0; while (aO < a.activeLength && bO < b.activeLength) { val aI = a.indexAt(aO); val bI = b.indexAt(bO); if (aI < bI) { aO += 1; } else if (bI < aI) { bO += 1; } else { rv(aI) = op(a.valueAt(aO), b.valueAt(bO)); aO += 1; bO += 1; } } rv; } /** Where either a or b has non-default values. */ def outer(a : SparseArray[V1], b : SparseArray[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new SparseArray[RV](a.length, scala.math.max(a.activeLength,b.activeLength)); var aO = 0; var bO = 0; while (aO < a.activeLength && bO < b.activeLength) { val aI = a.indexAt(aO); val bI = b.indexAt(bO); if (aI < bI) { rv(aI) = op(a.valueAt(aO), b.default); aO += 1; } else if (bI < aI) { rv(bI) = op(a.default, b.valueAt(bO)); bO += 1; } else { rv(aI) = op(a.valueAt(aO), b.valueAt(bO)); aO += 1; bO += 1; } } // process unpaired remaining from a while (aO < a.activeLength) { val aI = a.indexAt(aO); rv(aI) = op(a.valueAt(aO), b.default); aO += 1; } // process unpaired remaining from b while (bO < b.activeLength) { val bI = b.indexAt(bO); rv(bI) = op(a.default, b.valueAt(bO)); bO += 1; } rv; } /** All values regardless of whether default or not. */ def all(a : SparseArray[V1], b : SparseArray[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new SparseArray[RV](a.length, a.length); var i = 0; while (i < rv.length) { rv(i) = op(a(i),b(i)); i += 1; } rv; } } implicit def BinaryOpSparseArrayArray[V1,V2,RV,O<:OpType] (implicit op : BinaryOp[V1,V2,O,RV], c : CompatibleShape[V1,V2], d2 : DefaultArrayValue[V2], dv : DefaultArrayValue[RV], cm : ClassManifest[RV]) : BinaryOp[SparseArray[V1],Array[V2],O,SparseArray[RV]] = new BinaryOp[SparseArray[V1],Array[V2],O,SparseArray[RV]] { def opType = op.opType; def apply(a : SparseArray[V1], b : Array[V2]) = { // TODO: optimize allToSparse(a, b); } def inner(a : SparseArray[V1], b : Array[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new SparseArray[RV](a.length, a.activeLength); var o = 0; while (o < a.activeLength) { val i = a.indexAt(o); rv(i) = op(a.valueAt(o), b(i)); o += 1; } rv; } def allToDense(a : SparseArray[V1], b : Array[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new Array[RV](a.length); var i = 0; while (i < a.length) { rv(i) = op(a(i), b(i)); i += 1; } rv; } def allToSparse(a : SparseArray[V1], b : Array[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new SparseArray[RV](a.length, a.activeLength); var i = 0; while (i < a.length) { rv(i) = op(a(i), b(i)); i += 1; } rv; } } implicit def BinaryOpArraySparseArray[V1,V2,RV,O<:OpType] (implicit op : BinaryOp[V1,V2,O,RV], c : CompatibleShape[V1,V2], d1 : DefaultArrayValue[V1], dv : DefaultArrayValue[RV], cm : ClassManifest[RV]) : BinaryOp[Array[V1],SparseArray[V2],O,SparseArray[RV]] = new BinaryOp[Array[V1],SparseArray[V2],O,SparseArray[RV]] { def opType = op.opType; def apply(a : Array[V1], b : SparseArray[V2]) = { // TODO: optimize allToSparse(a, b); } def inner(a : Array[V1], b : SparseArray[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new SparseArray[RV](b.length, b.activeLength); var o = 0; while (o < b.activeLength) { val i = b.indexAt(o); rv(i) = op(a(i), b.valueAt(o)); o += 1; } rv; } def allToDense(a : Array[V1], b : SparseArray[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new Array[RV](b.length); var i = 0; while (i < a.length) { rv(i) = op(a(i), b(i)); i += 1; } rv; } def allToSparse(a : Array[V1], b : SparseArray[V2]) = { require(a.length == b.length, "arrays have different lengths"); val rv = new SparseArray[RV](b.length); var i = 0; while (i < a.length) { rv(i) = op(a(i), b(i)); i += 1; } rv; } } /** Recurse on elements within an array. */ implicit def BinaryUpdateOpRecurseSparseArraySparseArray[V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[SparseArray[V1], SparseArray[V2], O] = new BinaryUpdateOp[SparseArray[V1], SparseArray[V2], O] { def opType = op.opType; def apply(a : SparseArray[V1], b : SparseArray[V2]) = { require(a.length == b.length, "Inputs must be the same length"); var i = 0; while (i < a.length) { op(a(i),b(i)); i += 1; } } } /** Recurse on elements within an array. */ implicit def BinaryUpdateOpRecurseSparseArrayArray[V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[SparseArray[V1], Array[V2], O] = new BinaryUpdateOp[SparseArray[V1], Array[V2], O] { def opType = op.opType; def apply(a : SparseArray[V1], b : Array[V2]) = { require(a.length == b.length, "Inputs must be the same length"); var i = 0; while (i < a.length) { op(a(i),b(i)); i += 1; } } } /** Recurse on elements. */ implicit def BinaryUpdateOpRecurseSparseArrayScalar[V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], s : Scalar[V2]) : BinaryUpdateOp[SparseArray[V1], V2, O] = new BinaryUpdateOp[SparseArray[V1], V2, O] { def opType = op.opType; def apply(a : SparseArray[V1], b : V2) = { var i = 0; while (i < a.length) { op(a(i),b); i += 1; } } } ///** // * Base class for updating a SparseArray by another SparseArray. Considers // * only non-zeros in the left operand. Base class of MulInto. // * // * @author dramage // */ //class SparseArraySparseArrayUpdateLeftNZOp[V1,V2](implicit op : BinaryOp[V1,V2,V1]) //extends BinaryUpdateOp[SparseArray[V1],SparseArray[V2]] { // def apply(a : SparseArray[V1], b : SparseArray[V2]) = { // if (a.length != b.length) { // throw new DomainException(this.getClass.getSimpleName + ": arrays have different lengths"); // } // var aO = 0; // var bO = 0; // while (aO < a.activeLength && bO < b.activeLength) { // val aI = a.indexAt(aO); // val bI = b.indexAt(bO); // if (aI < bI) { // a(aI) = op(a.valueAt(aO), b.default); // aO += 1; // } else if (bI < aI) { // bO += 1; // } else { // a(aI) = op(a.valueAt(aO), b.valueAt(bO)); // aO += 1; // bO += 1; // } // } // // // process unpaired remaining from a // while (aO < a.activeLength) { // val aI = a.indexAt(aO); // a(aI) = op(a.valueAt(aO), b.default); // aO += 1; // } // } //} // ///** // * Base class for updating a SparseArray by another SparseArray. Considers // * non-zeros in either operand. Base class of AddInto. // * // * @author dramage // */ //class SparseArraySparseArrayUpdateEitherNZOp[V1,V2](implicit op : BinaryOp[V1,V2,V1]) //extends BinaryUpdateOp[SparseArray[V1],SparseArray[V2]] { // def apply(a : SparseArray[V1], b : SparseArray[V2]) = { // if (a.length != b.length) { // throw new DomainException(this.getClass.getSimpleName + ": arrays have different lengths"); // } // // var aO = 0; // var bO = 0; // while (aO < a.activeLength && bO < b.activeLength) { // val aI = a.indexAt(aO); // val bI = b.indexAt(bO); // if (aI < bI) { // a(aI) = op(a.valueAt(aO), b.default); // aO += 1; // } else if (bI < aI) { // a(bI) = op(a.default, b.valueAt(bO)); // bO += 1; // } else { // a(aI) = op(a.valueAt(aO), b.valueAt(bO)); // aO += 1; // bO += 1; // } // } // // // process unpaired remaining from a // while (aO < a.activeLength) { // val aI = a.indexAt(aO); // a(aI) = op(a.valueAt(aO), b.default); // aO += 1; // } // // // process unpaired remaining from b // while (bO < b.activeLength) { // val bI = b.indexAt(bO); // a(bI) = op(a.default, b.valueAt(bO)); // bO += 1; // } // } //} // ///** // * Base class for updating a SparseArray by another SparseArray. Considers // * all values. Base class of DivInto. // * // * @author dramage // */ //class SparseArraySparseArrayUpdateAllOp[V1,V2](implicit op : BinaryOp[V1,V2,V1]) //extends BinaryUpdateOp[SparseArray[V1],SparseArray[V2]] { // def apply(a : SparseArray[V1], b : SparseArray[V2]) = { // if (a.length != b.length) { // throw new DomainException(this.getClass.getSimpleName + ": arrays have different lengths"); // } // // /** Optimization: use OuterOp if the default value is itself default */ // if (try { op(a.default, b.default) == a.default } catch { case _ => false; }) { // (new SparseArraySparseArrayUpdateEitherNZOp[V1,V2]).apply(a,b); // } else { // var i = 0; // while (i < a.length) { // a(i) = op(a(i),b(i)); // i += 1; // } // } // } //} // //class SparseArrayScalarUpdateOp[V1,B](implicit op : BinaryOp[V1,B,V1], sb : Scalar[B]) //extends BinaryUpdateOp[SparseArray[V1],B] { // def apply(a : SparseArray[V1], b : B) = // a.transform(v => op(v, b)); //} } /** * Default value of type T as used by SparseArray. * * Note that this is not the same as a general default value for T, * say as used by DomainMap, because this value must be null for * all references types in order for SparseArray to work as expected. * * @author dramage */ sealed trait DefaultArrayValue[@specialized T] extends Serializable { def value : T; } object DefaultArrayValue { implicit object IntDefaultArrayValue extends DefaultArrayValue[Int] { override def value = 0; } implicit object ShortDefaultArrayValue extends DefaultArrayValue[Short] { override def value = 0.toShort; } implicit object LongDefaultArrayValue extends DefaultArrayValue[Long] { override def value = 0l; } implicit object ByteDefaultArrayValue extends DefaultArrayValue[Byte] { override def value = 0.toByte; } implicit object CharDefaultArrayValue extends DefaultArrayValue[Char] { override def value = 0.toChar; } implicit object FloatDefaultArrayValue extends DefaultArrayValue[Float] { override def value = 0.0f; } implicit object DoubleDefaultArrayValue extends DefaultArrayValue[Double] { override def value = 0.0; } implicit object BooleanDefaultArrayValue extends DefaultArrayValue[Boolean] { override def value = false; } val refDefault = new DefaultArrayValue[AnyRef] { override def value : AnyRef = null; } implicit def ObjectDefaultArrayValue[T<:AnyRef] = refDefault.asInstanceOf[DefaultArrayValue[T]]; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanAppendColumns.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.scalar._; import scalala.tensor.domain.DomainException; import scalala.collection.sparse.{SparseArray,DefaultArrayValue}; /** * Construction delegate for appending columns with A | B. * * @author dramage */ trait CanAppendColumns[A,-B,+That] extends Function2[A,B,That]; ================================================ FILE: src/main/scala/scalala/generic/collection/CanBuildTensorForBinaryOp.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.tensor.domain.CanGetDomain; import scalala.tensor.generic.TensorBuilder; import scalala.tensor.Tensor; /** * Trait for building a new tensor from either A or B depending on the * given Op. Default to building tensor for left operand. * * @author dramage */ trait CanBuildTensorForBinaryOp[-A, -B, D, K, V, Op, +To] { def apply(a : A, b : B, domain : D) : TensorBuilder[K,V,To]; } object CanBuildTensorForBinaryOp { implicit def canBuildTensorLeft[A,B,D,K,V,Op,To] (implicit va : A=>Tensor[_,_], bf : CanBuildTensorFrom[A,D,K,V,To]) : CanBuildTensorForBinaryOp[A,B,D,K,V,Op,To] = new CanBuildTensorForBinaryOp[A,B,D,K,V,Op,To] { def apply(a : A, b : B, domain : D) = bf.apply(a, domain); } } ================================================ FILE: src/main/scala/scalala/generic/collection/CanBuildTensorFrom.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.tensor._; import scalala.tensor.domain._; import scalala.tensor.dense._; import scalala.tensor.generic.TensorBuilder; import scalala.scalar.Scalar; /** * Trait for constructing a lazy view of a given Tensor. * * @author dramage */ trait CanBuildTensorFrom[-From, -Domain, K, V, +To] { def apply(from : From, domain : Domain) : TensorBuilder[K,V,To]; } /** * Base level implicits take any tensor and any domain. * * @author dramage */ trait CanBuildTensorFromImplicitsLevel0 { implicit def canBuildTensorFromTensor[K,V:Scalar] : CanBuildTensorFrom[Tensor[_,_], IterableDomain[K], K, V, mutable.Tensor[K,V]] = new CanBuildTensorFrom[Tensor[_,_], IterableDomain[K], K, V, mutable.Tensor[K,V]] { override def apply(from : Tensor[_,_], domain : IterableDomain[K]) = from.newBuilder(domain).asInstanceOf[TensorBuilder[K,V,mutable.Tensor[K,V]]]; } } /** * Implicits that take any shaped tensor (Tensor1Row, Tensor1Col, Tensor2) * and a shaped domain and return a similarly shaped tensor. * * @author dramage */ trait CanBuildTensorFromImplicitsLevel1 extends CanBuildTensorFromImplicitsLevel0 { implicit def canBuildTensor1RowFromTensor1Row[K,V:Scalar] : CanBuildTensorFrom[Tensor1Row[_,_], Domain1[K], K, V, mutable.Tensor1Row[K,V]] = new CanBuildTensorFrom[Tensor1Row[_,_], Domain1[K], K, V, mutable.Tensor1Row[K,V]] { override def apply(from : Tensor1Row[_,_], domain : Domain1[K]) = from.newBuilder(domain).asInstanceOf[TensorBuilder[K,V,mutable.Tensor1Row[K,V]]]; } implicit def canBuildTensor1ColFromTensor1Row[K,V:Scalar] : CanBuildTensorFrom[Tensor1Col[_,_], Domain1[K], K, V, mutable.Tensor1Col[K,V]] = new CanBuildTensorFrom[Tensor1Col[_,_], Domain1[K], K, V, mutable.Tensor1Col[K,V]] { override def apply(from : Tensor1Col[_,_], domain : Domain1[K]) = from.newBuilder(domain).asInstanceOf[TensorBuilder[K,V,mutable.Tensor1Col[K,V]]]; } implicit def canBuildTensor2FromTensor[K1,K2,V:Scalar] : CanBuildTensorFrom[Tensor[_,_], Domain2[K1,K2], (K1,K2), V, mutable.Tensor2[K1,K2,V]] = new CanBuildTensorFrom[Tensor[_,_], Domain2[K1,K2], (K1,K2), V, mutable.Tensor2[K1,K2,V]] { override def apply(from : Tensor[_,_], domain : Domain2[K1,K2]) = from.newBuilder(domain).asInstanceOf[TensorBuilder[(K1,K2),V,mutable.Tensor2[K1,K2,V]]]; } } /** * Implicits that take any tensor and a vector/matrix domain and return a * vector or matrix. * * @author dramage */ trait CanBuildTensorFromImplicitsLevel2 extends CanBuildTensorFromImplicitsLevel1 { implicit def canBuildVectorColFromTensor[V:Scalar] : CanBuildTensorFrom[Tensor[_,_], IndexDomain, Int, V, mutable.VectorCol[V]] = new CanBuildTensorFrom[Tensor[_,_], IndexDomain, Int, V, mutable.VectorCol[V]] { override def apply(from : Tensor[_,_], domain : IndexDomain) = from.newBuilder(domain).asInstanceOf[TensorBuilder[Int,V,mutable.VectorCol[V]]]; } implicit def canBuildMatrixFromTensor[V:Scalar] : CanBuildTensorFrom[Tensor[_,_], TableDomain, (Int,Int), V, mutable.Matrix[V]] = new CanBuildTensorFrom[Tensor[_,_], TableDomain, (Int,Int), V, mutable.Matrix[V]] { override def apply(from : Tensor[_,_], domain : TableDomain) = from.newBuilder(domain).asInstanceOf[TensorBuilder[(Int,Int),V,mutable.Matrix[V]]]; } } /** * Keep row shape in Level 2. * * @author dramage */ trait CanBuildTensorFromImplicitsLevel2Row extends CanBuildTensorFromImplicitsLevel2 { implicit def canBuildVectorRowFromTensor1Row[V:Scalar] : CanBuildTensorFrom[Tensor1Row[_,_], IndexDomain, Int, V, mutable.VectorRow[V]] = new CanBuildTensorFrom[Tensor1Row[_,_], IndexDomain, Int, V, mutable.VectorRow[V]] { override def apply(from : Tensor1Row[_,_], domain : IndexDomain) = from.newBuilder(domain).asInstanceOf[TensorBuilder[Int,V,mutable.VectorRow[V]]]; } } /** * Implicits that keep the type and shape of common input vectors and matrices. * * @author dramage */ trait CanBuildTensorFromImplicitsLevel3 extends CanBuildTensorFromImplicitsLevel2Row { import dense._; import sparse._; import tensor.{Counter,Counter2}; implicit def canBuildCounterFromCounter[K,V:Scalar] : CanBuildTensorFrom[Counter[_,_], Domain1[K], K, V, mutable.Counter[K,V]] = new CanBuildTensorFrom[Counter[_,_], Domain1[K], K, V, mutable.Counter[K,V]] { override def apply(from : Counter[_,_], domain : Domain1[K]) = from.newBuilder(domain).asInstanceOf[TensorBuilder[K,V,mutable.Counter[K,V]]]; } implicit def canBuildCounter2FromCounter2[K1,K2,V:Scalar] : CanBuildTensorFrom[Counter2[_,_,_], Domain2[K1,K2], (K1,K2), V, mutable.Counter2[K1,K2,V]] = new CanBuildTensorFrom[Counter2[_,_,_], Domain2[K1,K2], (K1,K2), V, mutable.Counter2[K1,K2,V]] { override def apply(from : Counter2[_,_,_], domain : Domain2[K1,K2]) = from.newBuilder(domain).asInstanceOf[TensorBuilder[(K1,K2),V,mutable.Counter2[K1,K2,V]]]; } implicit def canBuildCounterFromCounter2[K,V:Scalar] : CanBuildTensorFrom[Counter2[_,_,_], Domain1[K], K, V, mutable.Counter[K,V]] = new CanBuildTensorFrom[Counter2[_,_,_], Domain1[K], K, V, mutable.Counter[K,V]] { override def apply(from : Counter2[_,_,_], domain : Domain1[K]) = from.newBuilder(domain).asInstanceOf[TensorBuilder[K,V,mutable.Counter[K,V]]]; } implicit def canBuildCounter2FromCounter[K1,K2,V:Scalar] : CanBuildTensorFrom[Counter[_,_], Domain2[K1,K2], (K1,K2), V, mutable.Counter2[K1,K2,V]] = new CanBuildTensorFrom[Counter[_,_], Domain2[K1,K2], (K1,K2), V, mutable.Counter2[K1,K2,V]] { override def apply(from : Counter[_,_], domain : Domain2[K1,K2]) = from.newBuilder(domain).asInstanceOf[TensorBuilder[(K1,K2),V,mutable.Counter2[K1,K2,V]]]; } implicit def canBuildDenseVectorColFromDenseTensor[V:Scalar] : CanBuildTensorFrom[DenseArrayTensor[_,_], IndexDomain, Int, V, DenseVectorCol[V]] = new CanBuildTensorFrom[DenseArrayTensor[_,_], IndexDomain, Int, V, DenseVectorCol[V]] { override def apply(from : DenseArrayTensor[_,_], domain : IndexDomain) = from.newBuilder(domain).asInstanceOf[TensorBuilder[Int,V,DenseVectorCol[V]]]; } implicit def canBuildDenseMatrixFromDenseTensor[V:Scalar] : CanBuildTensorFrom[DenseArrayTensor[_,_], TableDomain, (Int,Int), V, DenseMatrix[V]] = new CanBuildTensorFrom[DenseArrayTensor[_,_], TableDomain, (Int,Int), V, DenseMatrix[V]] { override def apply(from : DenseArrayTensor[_,_], domain : TableDomain) = from.newBuilder(domain).asInstanceOf[TensorBuilder[(Int,Int),V,DenseMatrix[V]]]; } implicit def canBuildSparseVectorColFromSparseTensor[V:Scalar] : CanBuildTensorFrom[SparseArrayTensor[_,_], IndexDomain, Int, V, SparseVectorCol[V]] = new CanBuildTensorFrom[SparseArrayTensor[_,_], IndexDomain, Int, V, SparseVectorCol[V]] { override def apply(from : SparseArrayTensor[_,_], domain : IndexDomain) = from.newBuilder(domain).asInstanceOf[TensorBuilder[Int,V,SparseVectorCol[V]]]; } } /** * Keep row shape in Level 3. * * @author dramage */ trait CanBuildTensorFromImplicitsLevel3Row extends CanBuildTensorFromImplicitsLevel3 { import dense._; import sparse._; implicit def canBuildDenseVectorRowFromDenseVectorRow[V:Scalar] : CanBuildTensorFrom[DenseVectorRow[_], IndexDomain, Int, V, DenseVectorRow[V]] = new CanBuildTensorFrom[DenseVectorRow[_], IndexDomain, Int, V, DenseVectorRow[V]] { override def apply(from : DenseVectorRow[_], domain : IndexDomain) = from.newBuilder(domain).asInstanceOf[TensorBuilder[Int,V,DenseVectorRow[V]]]; } implicit def canBuildSparseVectorRowFromSparseVectorRow[V:Scalar] : CanBuildTensorFrom[SparseVectorRow[_], IndexDomain, Int, V, SparseVectorRow[V]] = new CanBuildTensorFrom[SparseVectorRow[_], IndexDomain, Int, V, SparseVectorRow[V]] { override def apply(from : SparseVectorRow[_], domain : IndexDomain) = from.newBuilder(domain).asInstanceOf[TensorBuilder[Int,V,SparseVectorRow[V]]]; } } object CanBuildTensorFrom extends CanBuildTensorFromImplicitsLevel3Row; ================================================ FILE: src/main/scala/scalala/generic/collection/CanCopy.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.scalar.Scalar; /** * Marker for being able to copy a collection * * @author dlwh */ trait CanCopy[T] { // Should not inherit from T=>T because those get used by the compiler. def apply(t: T):T } object CanCopy { class OpArray[@specialized V:ClassManifest:Scalar] extends CanCreateZerosLike[Array[V],Array[V]] { override def apply(from : Array[V]) = { Array.fill(from.length)(implicitly[Scalar[V]].zero); } } class OpMapValues[From,A](implicit op : CanCopy[A], map : CanMapValues[From,A,A,From]) extends CanCopy[From] { def apply(v : From) = map.map(v, op.apply(_)); } implicit def opMapValues[From,A](implicit map : CanMapValues[From,A,A,From], op : CanCopy[A]) : CanCopy[From] = new OpMapValues[From,A]()(op, map); implicit def OpArrayAny[V:ClassManifest:Scalar] : OpArray[V] = new OpArray[V]; implicit object OpArrayI extends OpArray[Int]; implicit object OpArrayS extends OpArray[Short]; implicit object OpArrayL extends OpArray[Long]; implicit object OpArrayF extends OpArray[Float]; implicit object OpArrayD extends OpArray[Double]; implicit def canCopyScalar[V:Scalar]:CanCopy[V] = new CanCopy[V] { def apply(v1: V) = v1; } } ================================================ FILE: src/main/scala/scalala/generic/collection/CanCreateZerosLike.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.collection.sparse.{SparseArray,DefaultArrayValue}; import scalala.scalar.Scalar; /** * Marker for being able to create a collection of the same shape as * the given input but with zero values everywhere. * * @author dramage */ trait CanCreateZerosLike[-From, +To] { // Should not inherit from Form=>To because the compiler will try to use it to coerce types. def apply(from: From):To }; object CanCreateZerosLike { class OpArray[@specialized V:ClassManifest:Scalar] extends CanCreateZerosLike[Array[V],Array[V]] { override def apply(from : Array[V]) = { Array.fill(from.length)(implicitly[Scalar[V]].zero); } } class OpMapValues[From,A,To](implicit op : Scalar[A], map : CanMapValues[From,A,A,To]) extends CanCreateZerosLike[From,To] { def apply(v : From) = map.map(v, _ => op.zero); } implicit def opMapValues[From,A,To](implicit map : CanMapValues[From,A,A,To], op : Scalar[A]) : CanCreateZerosLike[From,To] = new OpMapValues[From,A,To]()(op, map); implicit def OpArrayAny[V:ClassManifest:Scalar] : OpArray[V] = new OpArray[V]; implicit object OpArrayI extends OpArray[Int]; implicit object OpArrayS extends OpArray[Short]; implicit object OpArrayL extends OpArray[Long]; implicit object OpArrayF extends OpArray[Float]; implicit object OpArrayD extends OpArray[Double]; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanFilterValues.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.collection.sparse.{SparseArray,DefaultArrayValue}; /** * Marker for being able to filter the values in a value collection. * * @author dramage */ trait CanFilterValues[From, @specialized A, +To] { /** Maps all values from the given collection. */ def filter(from : From, fn : (A=>Boolean)) : To; /** Maps all non-zero values from the given collection. */ def filterNonZero(from : From, fn : (A=>Boolean)) : To; } object CanFilterValues { type Op[From,A,To] = CanFilterValues[From,A,To]; // // Arrays // class OpArray[@specialized A:ClassManifest] extends Op[Array[A],A,Array[A]] { def filter(from : Array[A], fn : (A=>Boolean)) = from.filter(fn); def filterNonZero(from : Array[A], fn : (A => Boolean)) = this.filter(from, fn); } implicit def opArray[@specialized A:ClassManifest] = new OpArray[A]; implicit object OpArrayI extends OpArray[Int]; implicit object OpArrayS extends OpArray[Short]; implicit object OpArrayL extends OpArray[Long]; implicit object OpArrayF extends OpArray[Float]; implicit object OpArrayD extends OpArray[Double]; // // SparseArrays // class OpSparseArray[@specialized V:ClassManifest:DefaultArrayValue] extends Op[SparseArray[V],V,SparseArray[V]] { def filter(from : SparseArray[V], fn : (V=>Boolean)) = from.filter(fn); def filterNonZero(from : SparseArray[V], fn : (V=>Boolean)) = { val rv = new SparseArray[V](from.length, from.activeLength); from.foreachActivePair((k,v) => if (fn(v)) { rv(k) = v; }); rv.compact; rv; } } implicit def opSparseArray[@specialized V:ClassManifest:DefaultArrayValue] = new OpSparseArray[V]; implicit object OpSparseArrayI extends OpSparseArray[Int]; implicit object OpSparseArrayS extends OpSparseArray[Short]; implicit object OpSparseArrayL extends OpSparseArray[Long]; implicit object OpSparseArrayF extends OpSparseArray[Float]; implicit object OpSparseArrayD extends OpSparseArray[Double]; // // Scala maps // implicit def opMap[A, B, That](implicit bf : scala.collection.generic.CanBuildFrom[scala.collection.Map[A,B], (A,B), That]) = new OpMap[A,B,That]; class OpMap[A, B, That] extends Op[scala.collection.Map[A,B],B,scala.collection.Map[A,B]] { def filter(from : scala.collection.Map[A,B], fn : (B => Boolean)) = from.filter((tup : (A,B)) => fn(tup._2)); def filterNonZero(from : scala.collection.Map[A,B], fn : (B => Boolean)) = this.filter(from, fn); } } ================================================ FILE: src/main/scala/scalala/generic/collection/CanGetActiveValues.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.collection.sparse.SparseArray; /** * Marker for being able to get the domain (keys) of a collection. * * @author dramage */ trait CanGetActiveValues[-Coll, @specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] { def apply(coll : Coll) : Iterator[(K,V)]; } object CanGetActiveValues { class OpArray[V] extends CanGetActiveValues[Array[V],Int,V] { override def apply(coll : Array[V]) = Iterator.range(0, coll.length).map(i => (i, coll(i))); } implicit def opArray[V] = new OpArray[V]; implicit object OpArrayI extends OpArray[Int]; implicit object OpArrayS extends OpArray[Short]; implicit object OpArrayL extends OpArray[Long]; implicit object OpArrayF extends OpArray[Float]; implicit object OpArrayD extends OpArray[Double]; class OpSparseArray[V] extends CanGetActiveValues[SparseArray[V],Int,V] { override def apply(coll : SparseArray[V]) = coll.activeIterator; } implicit def opSparseArray[V] = new OpSparseArray[V]; implicit object OpSparseArrayI extends OpSparseArray[Int]; implicit object OpSparseArrayS extends OpSparseArray[Short]; implicit object OpSparseArrayL extends OpSparseArray[Long]; implicit object OpSparseArrayF extends OpSparseArray[Float]; implicit object OpSparseArrayD extends OpSparseArray[Double]; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanGetDouble.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; /** * Marker for being able to get the value of a map at a key as a double. * * @author dramage */ trait CanGetDouble[-Coll, @specialized(Int,Long) -K] { def apply(coll : Coll, key : K) : Double; } object CanGetDouble { type Op[Coll,K] = CanGetDouble[Coll,K]; implicit object OpArrayI extends Op[Array[Int],Int] { override def apply(coll : Array[Int], key : Int) = coll(key); } implicit object OpArrayS extends Op[Array[Short],Int] { override def apply(coll : Array[Short], key : Int) = coll(key); } implicit object OpArrayL extends Op[Array[Long],Int] { override def apply(coll : Array[Long], key : Int) = coll(key); } implicit object OpArrayF extends Op[Array[Float],Int] { override def apply(coll : Array[Float], key : Int) = coll(key); } implicit object OpArrayD extends Op[Array[Double],Int] { override def apply(coll : Array[Double], key : Int) = coll(key); } implicit def opIndexedSeq[@specialized V](implicit cv : V => Double) = new OpIndexedSeq[V]; class OpIndexedSeq[@specialized V](implicit cv : V => Double) extends CanGetDouble[IndexedSeq[V], Int] { def apply(coll : IndexedSeq[V], key : Int) = coll(key); } implicit object OpIndexedSeqI extends OpIndexedSeq[Int]; implicit object OpIndexedSeqC extends OpIndexedSeq[Char]; implicit object OpIndexedSeqS extends OpIndexedSeq[Short]; implicit object OpIndexedSeqL extends OpIndexedSeq[Long]; implicit object OpIndexedSeqF extends OpIndexedSeq[Float]; implicit object OpIndexedSeqD extends OpIndexedSeq[Double]; implicit def opMap[K,V](implicit cv : V => Double) = new OpMap[K,V]; class OpMap[K,V](implicit cv : V => Double) extends CanGetDouble[scala.collection.Map[K,V], K] { def apply(coll : scala.collection.Map[K,V], key : K) = coll(key); } } ================================================ FILE: src/main/scala/scalala/generic/collection/CanGetValue.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; /** * Marker for being able to get the value of a map at a key. * * @author dramage */ trait CanGetValue[-Coll, @specialized(Int,Long) -K, @specialized(Int,Long,Float,Double) +V] { def apply(coll : Coll, key : K) : V; } object CanGetValue { implicit def opArray[@specialized V] = new OpArray[V]; class OpArray[@specialized V] extends CanGetValue[Array[V], Int, V] { def apply(coll : Array[V], key : Int) = coll(key); } implicit object OpArrayI extends OpArray[Int]; implicit object OpArrayC extends OpArray[Char]; implicit object OpArrayS extends OpArray[Short]; implicit object OpArrayL extends OpArray[Long]; implicit object OpArrayF extends OpArray[Float]; implicit object OpArrayD extends OpArray[Double]; implicit object OpArrayB extends OpArray[Boolean]; implicit def opIndexedSeq[@specialized V] = new OpIndexedSeq[V]; class OpIndexedSeq[@specialized V] extends CanGetValue[IndexedSeq[V], Int, V] { def apply(coll : IndexedSeq[V], key : Int) = coll(key); } implicit object OpIndexedSeqI extends OpIndexedSeq[Int]; implicit object OpIndexedSeqC extends OpIndexedSeq[Char]; implicit object OpIndexedSeqS extends OpIndexedSeq[Short]; implicit object OpIndexedSeqL extends OpIndexedSeq[Long]; implicit object OpIndexedSeqF extends OpIndexedSeq[Float]; implicit object OpIndexedSeqD extends OpIndexedSeq[Double]; implicit object OpIndexedSeqB extends OpIndexedSeq[Boolean]; implicit def opMap[K,V] = new OpMap[K,V]; class OpMap[K,V] extends CanGetValue[scala.collection.Map[K,V], K, V] { def apply(coll : scala.collection.Map[K,V], key : K) = coll(key); } } ================================================ FILE: src/main/scala/scalala/generic/collection/CanJoin.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; /** * Trait for applying a function to two tensors across their underlying * shared keys -- either all keys or non-zero keys. The tensors must * have the same domain. * * @author dramage */ trait CanJoin[-A, -B, @specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V1, @specialized(Int,Long,Float,Double) V2] { /** Joins on all keys in the domain. */ def joinAll[RV](a : A, b : B, fn : (K,V1,V2)=>RV) : Unit; /** Joins when both a and b are non-zero. */ def joinBothNonZero[RV](a : A, b : B, fn : (K,V1,V2)=>RV) : Unit; /** Joins when either a or b is non-zero. */ def joinEitherNonZero[RV](a : A, b : B, fn : (K,V1,V2)=>RV) : Unit; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanMapKeyValuePairs.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; /** * Marker for being able to map the keys and values in a value collection * to new values. * * @author dramage */ trait CanMapKeyValuePairs[-From, +K, +A, -B, +To] { /** Maps all key-value pairs from the given collection. */ def map(from : From, fn : ((K,A) => B)) : To; /** Maps all non-zero key-value pairs from the given collection. */ def mapNonZero(from : From, fn : ((K,A) => B)) : To; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanMapValues.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.scalar.Complex import scalala.collection.sparse.{SparseArray,DefaultArrayValue}; /** * Marker for being able to map the values in a value collection. * * @author dramage */ trait CanMapValues[From, @specialized A, @specialized B, +To] { /** Maps all values from the given collection. */ def map(from : From, fn : (A=>B)) : To; /** Maps all non-zero values from the given collection. */ def mapNonZero(from : From, fn : (A=>B)) : To; } object CanMapValues { type Op[From,A,B,To] = CanMapValues[From,A,B,To]; // // Arrays // class OpArray[@specialized A, @specialized B:ClassManifest] extends Op[Array[A],A,B,Array[B]] { def map(from : Array[A], fn : (A=>B)) = from.map(fn); def mapNonZero(from : Array[A], fn : (A => B)) = this.map(from, fn); } implicit def opArray[@specialized A, @specialized B:ClassManifest] = new OpArray[A,B]; implicit object OpArrayII extends OpArray[Int,Int]; implicit object OpArraySS extends OpArray[Short,Short]; implicit object OpArrayLL extends OpArray[Long,Long]; implicit object OpArrayFF extends OpArray[Float,Float]; implicit object OpArrayDD extends OpArray[Double,Double]; implicit object OpArrayCC extends OpArray[Complex,Complex]; implicit object OpArrayID extends OpArray[Int,Double]; implicit object OpArraySD extends OpArray[Short,Double]; implicit object OpArrayLD extends OpArray[Long,Double]; implicit object OpArrayFD extends OpArray[Float,Double]; // // SparseArrays // class OpSparseArray[@specialized V, @specialized RV:ClassManifest:DefaultArrayValue] extends Op[SparseArray[V],V,RV,SparseArray[RV]] { def map(from : SparseArray[V], fn : (V=>RV)) = from.map(fn); def mapNonZero(from : SparseArray[V], fn : (V => RV)) = { val rv = new SparseArray[RV](from.length, from.activeLength); from.foreachActivePair((k,v) => rv(k) = fn(v)); rv; } } implicit def opSparseArray[@specialized V, @specialized RV:ClassManifest:DefaultArrayValue] = new OpSparseArray[V,RV]; implicit object OpSparseArrayII extends OpSparseArray[Int,Int]; implicit object OpSparseArraySS extends OpSparseArray[Short,Short]; implicit object OpSparseArrayLL extends OpSparseArray[Long,Long]; implicit object OpSparseArrayFF extends OpSparseArray[Float,Float]; implicit object OpSparseArrayDD extends OpSparseArray[Double,Double]; implicit object OpSparseArrayCC extends OpSparseArray[Complex,Complex]; implicit object OpSparseArrayID extends OpSparseArray[Int,Double]; implicit object OpSparseArraySD extends OpSparseArray[Short,Double]; implicit object OpSparseArrayLD extends OpSparseArray[Long,Double]; implicit object OpSparseArrayFD extends OpSparseArray[Float,Double]; // // Scala maps // implicit def opMap[A, B, O, That](implicit bf : scala.collection.generic.CanBuildFrom[scala.collection.Map[A,B], (A,O), That]) = new OpMap[A,B,O,That]; class OpMap[K, A, B, That](implicit bf : scala.collection.generic.CanBuildFrom[scala.collection.Map[K,A], (K,B), That]) extends Op[scala.collection.Map[K,A],A,B,That] { def map(from : scala.collection.Map[K,A], fn : (A => B)) = from.map(tup => (tup._1, fn(tup._2))); def mapNonZero(from : scala.collection.Map[K,A], fn : (A => B)) = this.map(from, fn); } } ================================================ FILE: src/main/scala/scalala/generic/collection/CanSliceMatrix.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; /** * Builder trait for a slicing a view of a matrix. * * @author dramage */ trait CanSliceMatrix[-From, A1, A2, +To] { def apply(from : From, keys1 : Seq[A1], keys2 : Seq[A2]) : To; } /** * Builder trait for a slicing a row from a matrix. * * @author dramage */ trait CanSliceRow[-From, K, +To] { def apply(from : From, row : K) : To; } /** * Builder trait for a slicing a column from a matrix. * * @author dramage */ trait CanSliceCol[-From, K, +To] { def apply(from : From, col : K) : To; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanSliceTensor.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; /** * Supports sliced view of a Tensor. * * @author dramage */ trait CanSliceTensor[-From, A1, A2, +To] { def apply(from : From, keymap : scala.collection.Map[A2,A1]) : To; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanSliceVector.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; /** * Capability trait for slicing a Vector from something. * * @author dramage */ trait CanSliceVector[-From, A, +To] { def apply(from : From, keys : Seq[A]) : To; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanTranspose.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scalala.tensor._; /** * Transpose of a shaped value. * * @author dramage */ trait CanTranspose[-From,+To] extends (From=>To); /** * Transpose non-mutable tensors. * * @author dramage */ trait CanTransposeImplicitsLevel0 { implicit def canTransposeTensor1Row[K,V] : CanTranspose[Tensor1Row[K,V],Tensor1Col[K,V]] = new CanTranspose[Tensor1Row[K,V],Tensor1Col[K,V]] { override def apply(from : Tensor1Row[K,V]) = from.t; } implicit def canTransposeTensor1Col[K,V] : CanTranspose[Tensor1Col[K,V],Tensor1Row[K,V]] = new CanTranspose[Tensor1Col[K,V],Tensor1Row[K,V]] { override def apply(from : Tensor1Col[K,V]) = from.t; } implicit def canTransposeTensor2[K2,K1,V] : CanTranspose[Tensor2[K1,K2,V],Tensor2[K2,K1,V]] = new CanTranspose[Tensor2[K1,K2,V],Tensor2[K2,K1,V]] { override def apply(from : Tensor2[K1,K2,V]) = { from.t; } } } trait CanTransposeImplicitsLevel0M extends CanTransposeImplicitsLevel0 { implicit def canTransposeMutableTensor1Col[K,V] : CanTranspose[mutable.Tensor1Col[K,V],mutable.Tensor1Row[K,V]] = new CanTranspose[mutable.Tensor1Col[K,V],mutable.Tensor1Row[K,V]] { override def apply(from : mutable.Tensor1Col[K,V]) = from.t; } implicit def canTransposeMutableTensor1Row[K,V] : CanTranspose[mutable.Tensor1Row[K,V],mutable.Tensor1Col[K,V]] = new CanTranspose[mutable.Tensor1Row[K,V],mutable.Tensor1Col[K,V]] { override def apply(from : mutable.Tensor1Row[K,V]) = from.t; } } trait CanTransposeImplicitsLevel1 extends CanTransposeImplicitsLevel0M { implicit def canTransposeVectorRow[V] : CanTranspose[VectorRow[V],VectorCol[V]] = new CanTranspose[VectorRow[V],VectorCol[V]] { override def apply(from : VectorRow[V]) = from.t; } implicit def canTransposeVectorCol[V] : CanTranspose[VectorCol[V],VectorRow[V]] = new CanTranspose[VectorCol[V],VectorRow[V]] { override def apply(from : VectorCol[V]) = from.t; } implicit def canTransposeMatrix[V] : CanTranspose[Matrix[V],Matrix[V]] = new CanTranspose[Matrix[V],Matrix[V]] { override def apply(from : Matrix[V]) = from.t; } } trait CanTransposeImplicitsLevel1M extends CanTransposeImplicitsLevel1 { implicit def canTransposeMutableVectorCol[V] : CanTranspose[mutable.VectorCol[V],mutable.VectorRow[V]] = new CanTranspose[mutable.VectorCol[V],mutable.VectorRow[V]] { override def apply(from : mutable.VectorCol[V]) = from.t; } implicit def canTransposeMutableVectorRow[V] : CanTranspose[mutable.VectorRow[V],mutable.VectorCol[V]] = new CanTranspose[mutable.VectorRow[V],mutable.VectorCol[V]] { override def apply(from : mutable.VectorRow[V]) = from.t; } implicit def canTransposeMutableMatrix[V] : CanTranspose[mutable.Matrix[V],mutable.Matrix[V]] = new CanTranspose[mutable.Matrix[V],mutable.Matrix[V]] { override def apply(from : mutable.Matrix[V]) = from.t; } } trait CanTransposeImplicitsLevel2 { implicit def canTransposeSparseVectorRow[V] : CanTranspose[sparse.SparseVectorRow[V],sparse.SparseVectorCol[V]] = new CanTranspose[sparse.SparseVectorRow[V],sparse.SparseVectorCol[V]] { override def apply(from : sparse.SparseVectorRow[V]) = from.t; } implicit def canTransposeSparseVectorCol[V] : CanTranspose[sparse.SparseVectorCol[V],sparse.SparseVectorRow[V]] = new CanTranspose[sparse.SparseVectorCol[V],sparse.SparseVectorRow[V]] { override def apply(from : sparse.SparseVectorCol[V]) = from.t; } implicit def canTransposeDenseVectorRow[V] : CanTranspose[dense.DenseVectorRow[V],dense.DenseVectorCol[V]] = new CanTranspose[dense.DenseVectorRow[V],dense.DenseVectorCol[V]] { override def apply(from : dense.DenseVectorRow[V]) = from.t; } implicit def canTransposeDenseVectorCol[V] : CanTranspose[dense.DenseVectorCol[V],dense.DenseVectorRow[V]] = new CanTranspose[dense.DenseVectorCol[V],dense.DenseVectorRow[V]] { override def apply(from : dense.DenseVectorCol[V]) = from.t; } } object CanTranspose extends CanTransposeImplicitsLevel2 { } ================================================ FILE: src/main/scala/scalala/generic/collection/CanView.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; /** * Trait for constructing a lazy view of a given Tensor. * * @author dramage */ trait CanView[-From, +To] { def apply(from : From) : To; } ================================================ FILE: src/main/scala/scalala/generic/collection/CanViewAsTensor1.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.collection.sparse.SparseArray; import scalala.scalar.Scalar; import scalala.tensor.Tensor1; import scalala.tensor.dense.DenseVectorCol; import scalala.tensor.sparse.SparseVectorCol; /** * View something as a Tensor1. * * @author dramage */ trait CanViewAsTensor1[-From,K,V] { def apply(from : From) : Tensor1[K,V]; } object CanViewAsTensor1 { // // View arrays // class ArrayTensor1[V:ClassManifest:Scalar] extends CanViewAsTensor1[Array[V],Int,V] { def apply(from : Array[V]) = new DenseVectorCol[V](from); } implicit def mkArrayTensor1[V:ClassManifest:Scalar] = new ArrayTensor1[V](); implicit object ArrayI extends ArrayTensor1[Int]; implicit object ArrayS extends ArrayTensor1[Short]; implicit object ArrayL extends ArrayTensor1[Long]; implicit object ArrayF extends ArrayTensor1[Float]; implicit object ArrayD extends ArrayTensor1[Double]; implicit object ArrayB extends ArrayTensor1[Boolean]; // // View sparse arrays // class SparseArrayTensor1[V:ClassManifest:Scalar] extends CanViewAsTensor1[SparseArray[V],Int,V] { def apply(from : SparseArray[V]) = new SparseVectorCol[V](from); } implicit def mkSparseArrayTensor1[V:ClassManifest:Scalar] = new SparseArrayTensor1[V](); implicit object SparseArrayI extends SparseArrayTensor1[Int]; implicit object SparseArrayS extends SparseArrayTensor1[Short]; implicit object SparseArrayL extends SparseArrayTensor1[Long]; implicit object SparseArrayF extends SparseArrayTensor1[Float]; implicit object SparseArrayD extends SparseArrayTensor1[Double]; implicit object SparseArrayB extends SparseArrayTensor1[Boolean]; // // View pre-constructed Tensor1 instances // class Tensor1Tensor1[K,V:Scalar] extends CanViewAsTensor1[Tensor1[K,V],K,V] { def apply(from : Tensor1[K,V]) = from; } implicit def mkTensor1Tensor1[K,V:Scalar] = new Tensor1Tensor1[K,V](); } ================================================ FILE: src/main/scala/scalala/generic/collection/CanViewAsTensor2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.scalar.Scalar; import scalala.tensor.Tensor2; import scalala.tensor.dense.ArrayArrayMatrix; /** * View something as a Tensor1. * * @author dramage */ trait CanViewAsTensor2[-From,K1,K2,V] { def apply(from : From) : Tensor2[K1,K2,V]; } object CanViewAsTensor2 { // // View arrays // class ArrayArrayTensor2[V:ClassManifest:Scalar] extends CanViewAsTensor2[Array[Array[V]],Int,Int,V] { def apply(from : Array[Array[V]]) = new ArrayArrayMatrix[V](from); } implicit def mkArrayArrayTensor2[V:ClassManifest:Scalar] = new ArrayArrayTensor2[V](); implicit object ArrayArrayI extends ArrayArrayTensor2[Int]; implicit object ArrayArrayS extends ArrayArrayTensor2[Short]; implicit object ArrayArrayL extends ArrayArrayTensor2[Long]; implicit object ArrayArrayF extends ArrayArrayTensor2[Float]; implicit object ArrayArrayD extends ArrayArrayTensor2[Double]; implicit object ArrayArrayB extends ArrayArrayTensor2[Boolean]; // // View pre-constructed Tensor2 instances // class Tensor2Tensor2[K1,K2,V:Scalar] extends CanViewAsTensor2[Tensor2[K1,K2,V],K1,K2,V] { def apply(from : Tensor2[K1,K2,V]) = from; } implicit def mkTensor2Tensor2[K1,K2,V:Scalar] = new Tensor2Tensor2[K1,K2,V](); } ================================================ FILE: src/main/scala/scalala/generic/collection/CanViewAsVector.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import scalala.collection.sparse.SparseArray; import scalala.scalar.Scalar; import scalala.tensor.Vector; import scalala.tensor.dense.DenseVectorCol; import scalala.tensor.sparse.SparseVectorCol; /** * View something as a Vector. * * @author dramage */ trait CanViewAsVector[-From,V] { def apply(from : From) : Vector[V]; } object CanViewAsVector { // // View arrays // class ArrayVector[V:ClassManifest:Scalar] extends CanViewAsVector[Array[V],V] { def apply(from : Array[V]) = new DenseVectorCol[V](from); } implicit def mkArrayVector[V:ClassManifest:Scalar] = new ArrayVector[V](); implicit object ArrayI extends ArrayVector[Int]; implicit object ArrayS extends ArrayVector[Short]; implicit object ArrayL extends ArrayVector[Long]; implicit object ArrayF extends ArrayVector[Float]; implicit object ArrayD extends ArrayVector[Double]; implicit object ArrayB extends ArrayVector[Boolean]; // // View sparse arrays // class SparseArrayVector[V:ClassManifest:Scalar] extends CanViewAsVector[SparseArray[V],V] { def apply(from : SparseArray[V]) = new SparseVectorCol[V](from); } implicit def mkSparseArrayVector[V:ClassManifest:Scalar] = new SparseArrayVector[V](); implicit object SparseArrayI extends SparseArrayVector[Int]; implicit object SparseArrayS extends SparseArrayVector[Short]; implicit object SparseArrayL extends SparseArrayVector[Long]; implicit object SparseArrayF extends SparseArrayVector[Float]; implicit object SparseArrayD extends SparseArrayVector[Double]; implicit object SparseArrayB extends SparseArrayVector[Boolean]; // // View pre-constructed Vector instances // class VectorVector[V:Scalar] extends CanViewAsVector[Vector[V],V] { def apply(from : Vector[V]) = from; } implicit def mkVectorVector[V:Scalar] = new VectorVector[V](); } ================================================ FILE: src/main/scala/scalala/generic/collection/CanZipMapValues.scala ================================================ package scalala package generic package collection /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ import scalala.scalar.Complex import scalala.collection.sparse.{SparseArray, DefaultArrayValue} import tensor.domain.CanGetDomain ; /** * Marker for being able to zip two From's and map the values to a new collection * * @author dlwh */ trait CanZipMapValues[From, @specialized A, @specialized B, +To] { /** Maps all corresponding values from the two collection. */ def map(from : From, from2: From, fn : (A,A)=>B) : To; } object CanZipMapValues { type Op[From, A, B, To] = CanZipMapValues[From, A, B, To]; // // Arrays // class OpArray[@specialized A, @specialized B: ClassManifest] extends Op[Array[A], A, B, Array[B]] { /**Maps all values from the given collection. */ def map(from: Array[A], from2: Array[A], fn: (A, A) => B) = { require(from.length == from2.length, "Array lengths don't match!") val arr = new Array[B](from.length) for(i <- 0 until from.length) { arr(i) = fn(from(i), from2(i)) } arr } } implicit def opArray[@specialized A, @specialized B: ClassManifest] = new OpArray[A, B]; implicit object OpArrayII extends OpArray[Int, Int]; implicit object OpArraySS extends OpArray[Short, Short]; implicit object OpArrayLL extends OpArray[Long, Long]; implicit object OpArrayFF extends OpArray[Float, Float]; implicit object OpArrayDD extends OpArray[Double, Double]; implicit object OpArrayCC extends OpArray[Complex, Complex]; implicit object OpArrayID extends OpArray[Int, Double]; implicit object OpArraySD extends OpArray[Short, Double]; implicit object OpArrayLD extends OpArray[Long, Double]; implicit object OpArrayFD extends OpArray[Float, Double]; implicit def canZipMapFromJoin[From,K,V,Domain,V2,To](implicit canJoin: CanJoin[From, From, K, V, V], dom: CanGetDomain[From, Domain], cbf: CanBuildTensorFrom[From, Domain, K, V2, To]):CanZipMapValues[From, V, V2, To] = { new CanZipMapValues[From, V, V2, To] { /**Maps all corresponding values from the two collection. */ def map(from: From, from2: From, fn: (V, V) => V2) = { val b = cbf(from, dom(from)) canJoin.joinAll(from, from2, {(k,v,v2) => b.update(k, fn(v,v2))}) b.result } } } } ================================================ FILE: src/main/scala/scalala/generic/math/CanAbs.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package math; import scalala.operators.UnaryOp import collection.CanMapValues /** * Operator type for abs(A). * * @author dramage */ trait OpAbs extends operators.OpType; object OpAbs extends OpAbs; /** * Construction delegate for abs(A). * * @author dlwh */ trait CanAbs[-A,+RV] extends UnaryOp[A,OpAbs,RV] { def opType = OpAbs; def apply(v: A):RV; } object CanAbs { implicit object OpI extends CanAbs[Int,Double] { def apply(v : Int) = scala.math.abs(v); } implicit object OpL extends CanAbs[Long,Double] { def apply(v : Long) = scala.math.abs(v); } implicit object OpF extends CanAbs[Float,Double] { def apply(v : Float) = scala.math.abs(v); } implicit object OpD extends CanAbs[Double,Double] { def apply(v : Double) = scala.math.abs(v); } class OpMapValues[From,A,B,To](implicit op : CanAbs[A,B], map : CanMapValues[From,A,B,To]) extends CanAbs[From,To] { def apply(v : From) = map.map(v, op.apply(_)); } implicit def opMapValues[From,A,B,To](implicit map : CanMapValues[From,A,B,To], op : CanAbs[A,B]) : CanAbs[From,To] = new OpMapValues[From,A,B,To]()(op, map); implicit object OpArrayI extends OpMapValues[Array[Int],Int,Double,Array[Double]]()(OpI,CanMapValues.OpArrayID); implicit object OpArrayL extends OpMapValues[Array[Long],Long,Double,Array[Double]]()(OpL,CanMapValues.OpArrayLD); implicit object OpArrayF extends OpMapValues[Array[Float],Float,Double,Array[Double]]()(OpF,CanMapValues.OpArrayFD); implicit object OpArrayD extends OpMapValues[Array[Double],Double,Double,Array[Double]]()(OpD,CanMapValues.OpArrayDD); } ================================================ FILE: src/main/scala/scalala/generic/math/CanExp.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package math; import collection.CanMapValues; import scalala.operators.{UnaryOp} import scalala.scalar.Complex import scalala.tensor.{Matrix, Vector} /** * Operator type for exp(A). * * @author dramage */ trait OpExp extends operators.OpType; object OpExp extends OpExp; /** * Constructiond delegate for exp(A). * * @author dramage */ trait CanExp[A,+RV] extends UnaryOp[A,OpExp,RV] { def opType = OpExp; } object CanExp { implicit object OpI extends CanExp[Int,Double] { def apply(v : Int) = scala.math.exp(v); } implicit object OpL extends CanExp[Long,Double] { def apply(v : Long) = scala.math.exp(v); } implicit object OpF extends CanExp[Float,Double] { def apply(v : Float) = scala.math.exp(v); } implicit object OpD extends CanExp[Double,Double] { def apply(v : Double) = scala.math.exp(v); } implicit object OpC extends CanExp[Complex,Complex] { def apply(v: Complex) = Complex(scala.math.cos(v.imag), scala.math.sin(v.imag)) * scala.math.exp(v.real) } class OpMapValues[From,A,B,To](implicit op : CanExp[A,B], map : CanMapValues[From,A,B,To]) extends CanExp[From,To] { def apply(v : From) = map.map(v, op.apply(_)); } implicit def opMapValues[From,A,B,To](implicit map : CanMapValues[From,A,B,To], op : CanExp[A,B]) : CanExp[From,To] = new OpMapValues[From,A,B,To]()(op, map); implicit object OpArrayI extends OpMapValues[Array[Int],Int,Double,Array[Double]]()(OpI,CanMapValues.OpArrayID); implicit object OpArrayL extends OpMapValues[Array[Long],Long,Double,Array[Double]]()(OpL,CanMapValues.OpArrayLD); implicit object OpArrayF extends OpMapValues[Array[Float],Float,Double,Array[Double]]()(OpF,CanMapValues.OpArrayFD); implicit object OpArrayD extends OpMapValues[Array[Double],Double,Double,Array[Double]]()(OpD,CanMapValues.OpArrayDD); implicit object OpArrayC extends OpMapValues[Array[Complex],Complex,Complex,Array[Complex]]()(OpC,CanMapValues.OpArrayCC); implicit object OpVectorI extends OpMapValues[Vector[Int],Int,Double,Vector[Double]]() implicit object OpVectorL extends OpMapValues[Vector[Long],Long,Double,Vector[Double]]() implicit object OpVectorF extends OpMapValues[Vector[Float],Float,Double,Vector[Double]]() implicit object OpVectorD extends OpMapValues[Vector[Double],Double,Double,Vector[Double]]() implicit object OpMatrixI extends OpMapValues[Matrix[Int],Int,Double,Matrix[Double]]() implicit object OpMatrixL extends OpMapValues[Matrix[Long],Long,Double,Matrix[Double]]() implicit object OpMatrixF extends OpMapValues[Matrix[Float],Float,Double,Matrix[Double]]() implicit object OpMatrixD extends OpMapValues[Matrix[Double],Double,Double,Matrix[Double]]() } ================================================ FILE: src/main/scala/scalala/generic/math/CanLog.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package math; import collection.CanMapValues; import scalala.operators.UnaryOp import tensor.{Matrix, Vector} ; /** * Operator type for log(A). * * @author dramage */ trait OpLog extends operators.OpType; object OpLog extends OpLog; /** * Constructiond delegate for log(A). * * @author dramage */ trait CanLog[-A,+RV] extends UnaryOp[A,OpLog,RV] { def opType = OpLog; } object CanLog { implicit object OpI extends CanLog[Int,Double] { def apply(v : Int) = scala.math.log(v); } implicit object OpL extends CanLog[Long,Double] { def apply(v : Long) = scala.math.log(v); } implicit object OpF extends CanLog[Float,Double] { def apply(v : Float) = scala.math.log(v); } implicit object OpD extends CanLog[Double,Double] { def apply(v : Double) = scala.math.log(v); } class OpMapValues[From,A,B,To](implicit op : CanLog[A,B], map : CanMapValues[From,A,B,To]) extends CanLog[From,To] { def apply(v : From) = map.map(v, op.apply(_)); } implicit def opMapValues[From,A,B,To](implicit map : CanMapValues[From,A,B,To], op : CanLog[A,B]) : CanLog[From,To] = new OpMapValues[From,A,B,To]()(op, map); implicit object OpArrayI extends OpMapValues[Array[Int],Int,Double,Array[Double]]()(OpI,CanMapValues.OpArrayID); implicit object OpArrayL extends OpMapValues[Array[Long],Long,Double,Array[Double]]()(OpL,CanMapValues.OpArrayLD); implicit object OpArrayF extends OpMapValues[Array[Float],Float,Double,Array[Double]]()(OpF,CanMapValues.OpArrayFD); implicit object OpArrayD extends OpMapValues[Array[Double],Double,Double,Array[Double]]()(OpD,CanMapValues.OpArrayDD); implicit object OpVectorI extends OpMapValues[Vector[Int],Int,Double,Vector[Double]]() implicit object OpVectorL extends OpMapValues[Vector[Long],Long,Double,Vector[Double]]() implicit object OpVectorF extends OpMapValues[Vector[Float],Float,Double,Vector[Double]]() implicit object OpVectorD extends OpMapValues[Vector[Double],Double,Double,Vector[Double]]() implicit object OpMatrixI extends OpMapValues[Matrix[Int],Int,Double,Matrix[Double]]() implicit object OpMatrixL extends OpMapValues[Matrix[Long],Long,Double,Matrix[Double]]() implicit object OpMatrixF extends OpMapValues[Matrix[Float],Float,Double,Matrix[Double]]() implicit object OpMatrixD extends OpMapValues[Matrix[Double],Double,Double,Matrix[Double]]() } ================================================ FILE: src/main/scala/scalala/generic/math/CanMean.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package math; import scalala.generic.collection.CanCreateZerosLike; import scalala.operators._; import scalala.tensor.Tensor; import scalala.scalar.ScalarDecimal; /** * Construction delegate for mean(From). * * @author dramage */ trait CanMean[-From,+To] extends (From=>To); trait LowPriorityCanMean { /** Computes the mean by adding and dividing. This is slower than the implementation in ZeroInto. */ implicit def AddDiv[V](implicit add : BinaryOp[V,V,OpAdd,V], div : BinaryOp[V,Int,OpDiv,V]) : CanMean[Traversable[V],V] = new CanMean[Traversable[V],V] { def apply(values : Traversable[V]) = { var current = values.head; var n = 0; for (value <- values) { if (n >= 1) { current = add(current, value); } n += 1; } div(current, n); } } } object CanMean { // extends LowPriorityCanMean { /** Numerically stable one-pass mean computation. */ implicit def TraversableOnceMeanScalar[S](implicit view : S=>Double) : CanMean[TraversableOnce[S],Double] = new CanMean[TraversableOnce[S],Double] { def apply(values : TraversableOnce[S]) = { var m = 0.0; var k = 0; for (x <- values) { k += 1; m += (x - m) / k; } m; } } /** Optimized implementation for array of doubles. */ implicit def ArrayMeanScalar[S](implicit view : S=>Double) : CanMean[Array[S],Double] = new CanMean[Array[S],Double] { def apply(values : Array[S]) = { var m = 0.0; var k = 0; while (k < values.length) { m += (values(k) - m) / (k + 1); k += 1; } m; } } /** Numerically stable generic one-pass mean computation. */ implicit def TensorMean[T,V,D](implicit tv : T=>Tensor[_,V], sd : ScalarDecimal[V,D], add : BinaryOp[D,D,OpAdd,D], sub : BinaryOp[V,D,OpSub,D], div : BinaryOp[D,Int,OpDiv,D], mul : BinaryOp[D,Double,OpMul,D]) : CanMean[T,D] = new CanMean[T,D] { def apply(tensor : T) = { var m = sd.decimal.zero; var k = 0; tensor.foreachNonZeroValue(x => { k += 1; m = add(m,div(sub(x,m),k)); }); mul(m, k.toDouble / tensor.size); } } /** Computes the mean by starting with zero, adding into it, and dividing into it. */ implicit def ZeroInto[V,RV](implicit zero : CanCreateZerosLike[V,RV], addInto : BinaryUpdateOp[RV,V,OpAdd], divInto : BinaryUpdateOp[RV,Int,OpDiv]) : CanMean[TraversableOnce[V],RV] = new CanMean[TraversableOnce[V],RV] { def apply(values : TraversableOnce[V]) : RV = { var sum : RV = null.asInstanceOf[RV]; var k = 0; for (value <- values) { if (k == 0) { sum = zero(value); } addInto(sum, value); k += 1; } divInto(sum, k); sum; } } } ================================================ FILE: src/main/scala/scalala/generic/math/CanNorm.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package math; import collection.CanViewAsTensor1; /** * Construction delegate for getting the norm of a value of type From. * * @author dramage */ trait CanNorm[-From] extends ((From,Double)=>Double); object CanNorm { implicit def mkTensor1Norm[T](implicit tt : CanViewAsTensor1[T,_,_]) : CanNorm[T] = new CanNorm[T] { def apply(t : T, n : Double) : Double = tt(t).norm(n); } } ================================================ FILE: src/main/scala/scalala/generic/math/CanSoftmax.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package math; import collection.CanViewAsTensor1; /** * Construction delegate for getting the softmax of a type. * * @author dlwh */ trait CanSoftmax[-From] { // shouldn't be apply, because function1's are bad implicits def softmax(x: From):Double } object CanSoftmax { implicit def mkTensor1Softmax[K,T](implicit tt : CanViewAsTensor1[T,K,Double]) : CanSoftmax[T] = new CanSoftmax[T] { def softmax(t : T) : Double = { val value = tt(t); val max = value.max; val part = value.valuesIterator.foldLeft(0.0)((acc,v) => acc + scala.math.exp(v - max)); max + scala.math.log(part); } } } ================================================ FILE: src/main/scala/scalala/generic/math/CanSqrt.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package math; import collection.CanMapValues; import scalala.operators.{UnaryOp,OpType}; trait OpSqrt extends OpType; object OpSqrt extends OpSqrt; /** * Constructiond delegate for sqrt(A). * * @author dramage */ trait CanSqrt[-A,+RV] extends UnaryOp[A,OpSqrt,RV] { def opType = OpSqrt; } object CanSqrt { implicit object OpI extends CanSqrt[Int,Double] { def apply(v : Int) = scala.math.sqrt(v); } implicit object OpL extends CanSqrt[Long,Double] { def apply(v : Long) = scala.math.sqrt(v); } implicit object OpF extends CanSqrt[Float,Double] { def apply(v : Float) = scala.math.sqrt(v); } implicit object OpD extends CanSqrt[Double,Double] { def apply(v : Double) = scala.math.sqrt(v); } class OpMapValues[From,A,B,To](implicit op : CanSqrt[A,B], map : CanMapValues[From,A,B,To]) extends CanSqrt[From,To] { def apply(v : From) = map.map(v, op.apply(_)); } implicit def opMapValues[From,A,B,To](implicit map : CanMapValues[From,A,B,To], op : CanSqrt[A,B]) : CanSqrt[From,To] = new OpMapValues[From,A,B,To]()(op, map); implicit object OpArrayI extends OpMapValues[Array[Int],Int,Double,Array[Double]]()(OpI,CanMapValues.OpArrayID); implicit object OpArrayL extends OpMapValues[Array[Long],Long,Double,Array[Double]]()(OpL,CanMapValues.OpArrayLD); implicit object OpArrayF extends OpMapValues[Array[Float],Float,Double,Array[Double]]()(OpF,CanMapValues.OpArrayFD); implicit object OpArrayD extends OpMapValues[Array[Double],Double,Double,Array[Double]]()(OpD,CanMapValues.OpArrayDD); } ================================================ FILE: src/main/scala/scalala/generic/math/CanVariance.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package math; import scalala.generic.collection.CanCreateZerosLike; import scalala.operators._; import scalala.tensor.Tensor; import scalala.scalar.ScalarDecimal; /** * Construction delegate for variance(From). * * @author dramage */ trait CanVariance[-From,+To] extends (From=>To); object CanVariance { /** * Numerically stable one-pass sample variance computation. * * From http://www.cs.berkeley.edu/~mhoemmen/cs194/Tutorials/variance.pdf */ implicit def TraversableOnceVarianceScalar[S](implicit view : S=>Double) : CanVariance[TraversableOnce[S],Double] = new CanVariance[TraversableOnce[S],Double] { def apply(values : TraversableOnce[S]) = { var m = 0.0; var q = 0.0; var k = 0; for (x <- values) { k += 1; val xMm = x - m; val xMmDk = xMm / k; m = m + xMmDk; q = q + (k - 1) * xMm * xMmDk } q / (k - 1); } } implicit def ArrayVarianceScalar[S](implicit view : S=>Double) : CanVariance[Array[S],Double] = new CanVariance[Array[S],Double] { def apply(values : Array[S]) = { var m = 0.0; var q = 0.0; var k = 0; while (k < values.length) { val x = values(k); k += 1; val xMm = x - m; val xMmDk = xMm / k; m = m + xMmDk; q = q + (k - 1) * xMm * xMmDk } q / (k - 1); } } implicit def TensorVariance[T,V,D](implicit view : T=>Tensor[_,V], sd : ScalarDecimal[V,D], sub : BinaryOp[V,D,OpSub,D], add : BinaryOp[D,D,OpAdd,D], div : BinaryOp[D,Int,OpDiv,D], mul1 : BinaryOp[D,D,OpMul,D], mul2 : BinaryOp[D,Int,OpMul,D]) : CanVariance[T,D] = new CanVariance[T,D] { override def apply(tensor : T) = { var m = sd.decimal.zero; var q = sd.decimal.zero; var k = 0; // TODO: this could be more efficient by using foreachNonZeroValue tensor.foreachValue(x => { k += 1; val xMm = sub(x, m); val xMmDk = div(xMm, k); m = add(m, xMmDk); q = add(q, mul2(mul1(xMm,xMmDk), k-1)); }); div(q, k-1); } } } ================================================ FILE: src/main/scala/scalala/library/Library.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; import scalala.generic.math._ import scalala.tensor.mutable.Counter; import tensor._ import dense._ import domain.CanGetDomain import scalar.Scalar import operators._ import scalala.generic.collection._ /** * Library of scalala basic mathematical functions. * * @author dramage, afwlehmann */ trait Library { // // Aliases to scala math package. // /** Alias for math.log. */ final def log(v : Double) : Double = scala.math.log(v); /** Alias for math.log1p. */ final def log1p(v : Double) : Double = scala.math.log1p(v); /** Alias for math.exp. */ final def exp(v : Double) : Double = scala.math.exp(v); /** Alias for math.pow. */ final def pow(base : Double, exponent : Double) : Double = scala.math.pow(base, exponent); /** Alias for math.abs. */ final def abs(v : Double) : Double = scala.math.abs(v); /** Alias for x.isNaN. */ final def isnan(x : Double) = java.lang.Double.isNaN(x); /** Alias for math.sqrt. */ final def sqrt(x : Double) = scala.math.sqrt(x); /** Alias for Double.NaN */ final val NaN = Double.NaN; /** Alias for Double.NaN */ final val nan = NaN; /** Alias for Double.PositiveInfinity */ final val Inf = Double.PositiveInfinity; /** Alias for Double.PositiveInfinity */ final val inf = Inf; // // Collection level operations // /** Take the log of the given value. */ def log[V,That](value : V)(implicit log : CanLog[V,That]) : That = log(value); /** Take the exp of the given value. */ def exp[V,That](value : V)(implicit exp : CanExp[V,That]) : That = exp(value); /** Take the log of the given value. */ def abs[V,That](value : V)(implicit abs : CanAbs[V,That]) : That = abs(value); /** Take the n-norm of the given values. */ def mean[V,That](value : V)(implicit mean : CanMean[V,That]) : That = mean(value); /** Take the n-norm of the given value. */ def norm[V](value : V, n : Double)(implicit norm : CanNorm[V]) : Double = norm(value, n); /** Take the sqrt of the given value. */ def sqrt[V,That](value : V)(implicit sqrt : CanSqrt[V,That]) : That = sqrt(value); /** Take the standard deviation of a collection. */ def stddev[V,VV,That](data : V) (implicit variance : CanVariance[V,VV], sqrt : CanSqrt[VV,That]) : That = sqrt(variance(data)); /** Take the variance of a collection. */ def variance[V,That](data : V)(implicit variance : CanVariance[V,That]) = variance(data); /** Take the softmax of a collection. */ def softmax[V](value: V)(implicit softmax: CanSoftmax[V]) : Double = softmax.softmax(value) sealed trait Axis; object Axis { type Value = Axis case object Horizontal extends Axis; case object Vertical extends Axis; } /** * Minimum vector of the given matrix along the specified axis. */ def min[T: Scalar](X: Matrix[T], axis: Axis.Value): DenseVector[T] = { axis match { case Axis.Horizontal => DenseVectorCol.tabulate[T](X.numRows)(X(_,::).min) case Axis.Vertical => DenseVectorRow.tabulate[T](X.numCols)(X(::,_).min) } } /** * Maximum vector of the given matrix along the specified axis. */ def max[T: Scalar](X: Matrix[T], axis: Axis.Value): DenseVector[T] = { axis match { case Axis.Horizontal => DenseVectorCol.tabulate[T](X.numRows)(X(_,::).max) case Axis.Vertical => DenseVectorRow.tabulate[T](X.numCols)(X(::,_).max) } } /** * Mean vector of the given matrix along the specified axis. */ def mean[@specialized T](X: Matrix[T], axis: Axis.Value)(implicit xv: T => Double) : DenseVector[Double] = { // TODO: This calculation of the mean is rather slow. It should // be transformed into several while loops. axis match { case Axis.Horizontal => var mu = DenseVector.zeros[Double](X.numRows) X foreachTriple ( (i, j, value) => mu(i) += (value - mu(i)) / (j + 1) ) mu case Axis.Vertical => var mu = DenseVector.zeros[Double](X.numCols) X foreachTriple ( (i, j, value) => mu(j) += (value - mu(j)) / (i + 1) ) mu.t } } /** * Creates a copy of the object using the CanCopy implicit. */ def copy[T](t: T)(implicit canCopy: CanCopy[T]) = canCopy(t) /** * The covariance matrix and mean of the given dataset X where the samples of * a multivariate random distribution are stacked along the given axis. */ def covariance(X: Matrix[Double], axis: Axis.Value = Axis.Horizontal): (DenseMatrix[Double], DenseVector[Double]) = { require(X.numCols > 0 && X.numRows > 0) axis match { case Axis.Horizontal => val dim = X.numRows val mu = DenseVector.tabulate[Double](dim)(X(_,0)) val Sigma = DenseMatrix.zeros[Double](dim, dim) var K = 1.0 for (i <- 1 until X.numCols) { val xMinusMu = X(::,i) - mu K += 1 mu += xMinusMu / K Sigma += xMinusMu * xMinusMu.t * (1d - 1d / K) } (Sigma / math.max(1, K-1), mu) case Axis.Vertical => val dim = X.numCols val mu = DenseVector.tabulate[Double](dim)(X(0,_)) val Sigma = DenseMatrix.zeros[Double](dim, dim) var K = 1.0 for (i <- 1 until X.numRows) { val xMinusMu = X(i,::) - mu K += 1 mu += xMinusMu / K Sigma += xMinusMu.t * xMinusMu * (1d - 1d / K) } (Sigma / math.max(1, K-1), mu) } } /** Sums the tensor2 along the horizontal axis */ def sum[K1,K2,V,T,ADomain,Row](matrix: T, axis: Axis.Horizontal.type = Axis.Horizontal) (implicit view: T=>Tensor2[K1,K2,V], sliceRows: CanSliceRow[T,K1,Row], opAdd: BinaryOp[Row,Row,OpAdd,Row]):Row = { matrix.domain._1.view.map(sliceRows(matrix,_)).reduceLeft(opAdd); } /** Sums the tensor2 along the vertical axis */ def sum[K1,K2,V,T,ADomain,Col](matrix: T, axis: Axis.Vertical.type) (implicit view: T=>Tensor2[K1,K2,V], sliceCols: CanSliceCol[T,K2,Col], opAdd: BinaryOp[Col,Col,OpAdd,Col]):Col = { matrix.domain._2.view.map(sliceCols(matrix,_)).reduceLeft(opAdd); } // // Constructors // /** Counts the given items. */ def count[X](items : TraversableOnce[X]) : Counter[X,Int] = Counter.count(items); // // normalization and log-normalization: // /** * Normalizes the argument such that its norm is 1.0 (with respect to the argument n). * Returns value if value's norm is 0. */ def normalize[V,K,That](value: V, n: Double)(implicit _norm: CanNorm[V], st: V<: NumericOps[V], sm: CanSoftmax[V], op : BinaryOp[V,Double,OpSub,V]): V = { val max = softmax(value) if(max.isInfinite) value else value - max; } /** * logs and then logNormalizes the argument such that the softmax is 0.0. * Returns value if value's softmax is -infinity */ def logAndNormalize[V](value: V)(implicit canLog : CanLog[V,V], view: V => NumericOps[V], sm: CanSoftmax[V], op : BinaryOp[V,Double,OpSub,V]):V = { logNormalize(log(value)) } def logAndNormalizeRows[T,K1,K2,Row,ADomain,That](matrix: T)(implicit view: T=>Tensor2[K1,K2,Double], domainA : CanGetDomain[T,ADomain], sliceRows: CanSliceRow[T,K1,Row], canLog: CanMapValues[Row,Double,Double,Row], view2: Row => Tensor1[K2,Double] with NumericOps[Row], sm: CanSoftmax[Row], op : BinaryOp[Row,Double,OpSub,Row], bf : CanBuildTensorFrom[T,ADomain,(K1,K2),Double,That]): That = { val builder = bf(matrix,domainA(matrix)); for(k1 <- matrix.domain._1) { val row: Row = sliceRows(matrix, k1); val ln: Row = logAndNormalize(row); for((k2,v) <- ln.pairsIterator) { builder(k1 -> k2) = v; } } builder.result; } /** * Generates a vector of linearly spaced values between a and b (inclusive). * The returned vector will have length elements, defaulting to 100. */ def linspace(a : Double, b : Double, length : Int = 100) : DenseVectorCol[Double] = { val increment = (b - a) / (length - 1); DenseVectorCol.tabulate(length)(i => a + increment * i); } } object Library extends Library; ================================================ FILE: src/main/scala/scalala/library/LinearAlgebra.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; import org.netlib.lapack._ import org.netlib.util.intW import operators._ import scalar.Scalar import generic.collection.CanViewAsVector import tensor.domain.TableDomain import tensor.dense.{DenseVector, DenseMatrix} import tensor.{DiagonalMatrix, MatrixSingularException, Matrix, Vector} /** * Basic linear algebraic operations. * * @author dlwh,dramage,retronym,afwlehmann,lancelet */ trait LinearAlgebra { @inline private def requireNonEmptyMatrix[V](mat: Matrix[V]) = if (mat.numCols == 0 || mat.numRows == 0) throw new MatrixEmptyException @inline private def requireSquareMatrix[V](mat: Matrix[V]) = if (mat.numRows != mat.numCols) throw new MatrixNotSquareException @inline private def requireSymmetricMatrix[V](mat: Matrix[V]) = { requireSquareMatrix(mat) for (i <- 0 until mat.numRows; j <- 0 until i) if (mat(i,j) != mat(j,i)) throw new MatrixNotSymmetricException } /** * Eigenvalue decomposition (right eigenvectors) * * This function returns the real and imaginary parts of the eigenvalues, * and the corresponding eigenvectors. For most (?) interesting matrices, * the imaginary part of all eigenvalues will be zero (and the corresponding * eigenvectors will be real). Any complex eigenvalues will appear in * complex-conjugate pairs, and the real and imaginary components of the * eigenvector for each pair will be in the corresponding columns of the * eigenvector matrix. Take the complex conjugate to find the second * eigenvector. * * Based on EVD.java from MTJ 0.9.12 */ def eig(m : Matrix[Double]): (DenseVector[Double], DenseVector[Double], DenseMatrix[Double]) = { requireNonEmptyMatrix(m) requireSquareMatrix(m) val n = m.numRows; // Allocate space for the decomposition var Wr = DenseVector.zeros[Double](n); var Wi = DenseVector.zeros[Double](n); var Vr = DenseMatrix.zeros[Double](n,n); // Find the needed workspace val worksize = Array.ofDim[Double](1); val info = new intW(0); LAPACK.getInstance.dgeev( "N", "V", n, Array.empty[Double], math.max(1,n), Array.empty[Double], Array.empty[Double], Array.empty[Double], math.max(1,n), Array.empty[Double], math.max(1,n), worksize, -1, info); // Allocate the workspace val lwork: Int = if (info.`val` != 0) math.max(1,4*n); else math.max(1,worksize(0).toInt); val work = Array.ofDim[Double](lwork); // Factor it! val A = new DenseMatrix(n,n,Array.ofDim[Double](n*n)); A := m LAPACK.getInstance.dgeev( "N", "V", n, A.data, math.max(1,n), Wr.data, Wi.data, Array.empty[Double], math.max(1,n), Vr.data, math.max(1,n), work, work.length, info); if (info.`val` > 0) throw new NotConvergedException(NotConvergedException.Iterations) else if (info.`val` < 0) throw new IllegalArgumentException() (Wr, Wi, Vr) } /** * Computes the SVD of a m by n matrix * Returns an m*m matrix U, a vector of singular values, and a n*n matrix V' */ def svd(mat: DenseMatrix[Double]):(DenseMatrix[Double],DenseVector[Double],DenseMatrix[Double]) = { requireNonEmptyMatrix(mat) val m = mat.numRows; val n = mat.numCols; val S = DenseVector.zeros[Double](m min n); val U = DenseMatrix.zeros[Double](m,m); val Vt = DenseMatrix.zeros[Double](n,n); val iwork = new Array[Int](8 * (m min n) ); val workSize = ( 3 * math.min(m, n) * math.min(m, n) + math.max(math.max(m, n), 4 * math.min(m, n) * math.min(m, n) + 4 * math.min(m, n)) ); val work = new Array[Double](workSize); val info = new intW(0); LAPACK.getInstance.dgesdd( "A", m, n, mat.copy.data, math.max(1,m), S.data, U.data, math.max(1,m), Vt.data, math.max(1,n), work,work.length,iwork, info); if (info.`val` > 0) throw new NotConvergedException(NotConvergedException.Iterations) else if (info.`val` < 0) throw new IllegalArgumentException() (U,S,Vt); } /** * Returns the Kronecker product of the two matrices a and b, * usually denoted a ⊗ b. */ def kron[V1,V2,RV](a : Matrix[V1], b : Matrix[V2])(implicit mul : BinaryOp[V1,V2,OpMul,RV], s : Scalar[RV]) : Matrix[RV] = { val builder = a.newBuilder[(Int,Int),RV](TableDomain(a.numRows * b.numRows, a.numCols * b.numCols)); a.foreachNonZeroTriple((ai,aj,av) => b.foreachNonZeroTriple((bi,bj,bv) => builder((ai * b.numRows + bi, aj * b.numCols + bj)) = mul(av, bv))); builder.result.asInstanceOf[Matrix[RV]]; } /** * Returns the rank of each element in the given vector, adjusting for * ties. */ def ranks[X,V](x : X)(implicit xvt : CanViewAsVector[X,V], ord : Ordering[V]) : Array[Double] = { val a = xvt(x); val as = a.argsort; val rv = new Array[Double](as.length); var i = 0; while (i < as.length) { // count number of tied values at rank i var numTiedValuesAtI = 1; while (i + numTiedValuesAtI < as.length && a(as(i + numTiedValuesAtI)) == a(as(i))) { numTiedValuesAtI += 1; } // set return value for next numTiedValuesAtI indexes in as val rank = 1 + i + (numTiedValuesAtI - 1) / 2.0; var j = 0; while (j < numTiedValuesAtI) { rv(as(i + j)) = rank; j += 1; } i += numTiedValuesAtI; } rv; } /** * The lower triangular portion of the given real quadratic matrix X. Note * that no check will be performed regarding the symmetry of X. */ def lowerTriangular[T: Scalar](X: Matrix[T]): DenseMatrix[T] = { val N = X.numRows val builder = X.newBuilder[(Int, Int), T](TableDomain(N, N)) for (i <- 0 until N; j <- 0 to i) builder((i,j)) = X(i,j) builder.result.asInstanceOf[DenseMatrix[T]] } /** * The upper triangular portion of the given real quadratic matrix X. Note * that no check will be performed regarding the symmetry of X. */ def upperTriangular[T: Scalar](X: Matrix[T]): DenseMatrix[T] = { val N = X.numRows val builder = X.newBuilder[(Int, Int), T](TableDomain(N, N)) for (i <- 0 until N; j <- i until N) builder((i,j)) = X(i,j) builder.result.asInstanceOf[DenseMatrix[T]] } /** * Computes the cholesky decomposition A of the given real symmetric * positive definite matrix X such that X = A A^T. * * XXX: For higher dimensionalities, the return value really should be a * sparse matrix due to its inherent lower triangular nature. */ def cholesky(X: Matrix[Double]): DenseMatrix[Double] = { requireNonEmptyMatrix(X) // As LAPACK doesn't check if the given matrix is in fact symmetric, // we have to do it here (or get rid of this time-waster as long as // the caller of this function is clearly aware that only the lower // triangular portion of the given matrix is used and there is no // check for symmetry). requireSymmetricMatrix(X) // Copy the lower triangular part of X. LAPACK will store the result in A val A: DenseMatrix[Double] = lowerTriangular(X) val N = X.numRows val info = new intW(0) LAPACK.getInstance.dpotrf( "L" /* lower triangular */, N /* number of rows */, A.data, math.max(1, N) /* LDA */, info ) // A value of info.`val` < 0 would tell us that the i-th argument // of the call to dpotrf was erroneous (where i == |info.`val`|). assert(info.`val` >= 0) if (info.`val` > 0) throw new NotConvergedException(NotConvergedException.Iterations) A } /** * QR Factorization with pivoting * * input: A m x n matrix * output: (Q,R,P,pvt) where AP = QR * Q: m x m * R: m x n * P: n x n : permutation matrix (P(pvt(i),i) = 1) * pvt : pivot indices */ def qrp(A: DenseMatrix[Double]): (DenseMatrix[Double], DenseMatrix[Double], DenseMatrix[Int], Array[Int]) = { val m = A.numRows val n = A.numCols val lapack = LAPACK.getInstance(); //Get optimal workspace size // we do this by sending -1 as lwork to the lapack function val work = new Array[Double](1) var info = new intW(0) lapack.dgeqrf(m, n, null, m, null, work, -1, info); val lwork1 = if(info.`val` != 0) n else work(0).toInt lapack.dorgqr(m, m, math.min(m,n), null, m, null, work, -1, info); val lwork2 = if(info.`val` != 0) n else work(0).toInt; //allocate workspace mem. as max of lwork1 and lwork3 val workspace = new Array[Double](math.max(lwork1, lwork2)); //Perform the QR factorization with dgep3 val maxd = math.max(m,n) val AFact = DenseMatrix.zeros[Double](m,maxd) val pvt = new Array[Int](n) val tau = new Array[Double](math.min(m,n)) for(r <- 0 until m; c <- 0 until n) AFact(r,c) = A(r,c) lapack.dgeqp3(m, n, AFact.data, m, pvt, tau, workspace, workspace.length, info); //Error check if (info.`val` > 0) throw new NotConvergedException(NotConvergedException.Iterations) else if (info.`val` < 0) throw new IllegalArgumentException() //Get R val R = DenseMatrix.zeros[Double](m,n) for(c <- 0 until maxd if(c < n); r <- 0 until m if(r <= c)) R(r,c) = AFact(r,c) //Get Q from the matrix returned by dgep3 val Q = DenseMatrix.zeros[Double](m,m) lapack.dorgqr(m, m, math.min(m,n), AFact.data, m, tau, workspace, workspace.length, info); for(r <- 0 until m; c <- 0 until maxd if(c < m)) Q(r,c) = AFact(r,c) //Error check if (info.`val` > 0) throw new NotConvergedException(NotConvergedException.Iterations) else if (info.`val` < 0) throw new IllegalArgumentException() //Get P for(i <- 0 until pvt.length) pvt(i)-=1 val P = DenseMatrix.zeros[Int](n,n) for(i <- 0 until n) P(pvt(i), i) = 1 (Q,R,P,pvt) } /** * QR Factorization * * input: A m x n matrix * optional: skipQ - if true, don't reconstruct orthogonal matrix Q (instead returns (null,R)) * output: (Q,R) * Q: m x m * R: m x n */ def qr(A: DenseMatrix[Double], skipQ : Boolean = false): (DenseMatrix[Double], DenseMatrix[Double]) = { val m = A.numRows val n = A.numCols val lapack = LAPACK.getInstance(); //Get optimal workspace size // we do this by sending -1 as lwork to the lapack function val work = new Array[Double](1) var info = new intW(0) lapack.dgeqrf(m, n, null, m, null, work, -1, info); val lwork1 = if(info.`val` != 0) n else work(0).toInt lapack.dorgqr(m, m, math.min(m,n), null, m, null, work, -1, info); val lwork2 = if(info.`val` != 0) n else work(0).toInt; //allocate workspace mem. as max of lwork1 and lwork3 val workspace = new Array[Double](math.max(lwork1, lwork2)); //Perform the QR factorization with dgeqrf val maxd = math.max(m,n) val mind = math.max(m,n) val tau = new Array[Double](mind) val outputMat = DenseMatrix.zeros[Double](m,maxd) for(r <- 0 until m; c <- 0 until n) outputMat(r,c) = A(r,c) lapack.dgeqrf(m, n, outputMat.data, m, tau, workspace, workspace.length, info); //Error check if (info.`val` > 0) throw new NotConvergedException(NotConvergedException.Iterations) else if (info.`val` < 0) throw new IllegalArgumentException() //Get R val R = DenseMatrix.zeros[Double](m,n) for(c <- 0 until maxd if(c < n); r <- 0 until m if(r <= c)) R(r,c) = outputMat(r,c) //unless the skipq flag is set if(!skipQ){ //Get Q from the matrix returned by dgep3 val Q = DenseMatrix.zeros[Double](m,m) lapack.dorgqr(m, m, math.min(m,n), outputMat.data, m, tau, workspace, workspace.length, info); for(r <- 0 until m; c <- 0 until maxd if(c < m)) Q(r,c) = outputMat(r,c) //Error check if (info.`val` > 0) throw new NotConvergedException(NotConvergedException.Iterations) else if (info.`val` < 0) throw new IllegalArgumentException() (Q,R) } //skip Q and just return R else (null,R) } /** * Computes all eigenvalues (and optionally right eigenvectors) of the given * real symmetric matrix X. */ def eigSym(X: Matrix[Double], rightEigenvectors: Boolean): (DenseVector[Double], Option[DenseMatrix[Double]]) = { requireNonEmptyMatrix(X) // As LAPACK doesn't check if the given matrix is in fact symmetric, // we have to do it here (or get rid of this time-waster as long as // the caller of this function is clearly aware that only the lower // triangular portion of the given matrix is used and there is no // check for symmetry). requireSymmetricMatrix(X) // Copy the lower triangular part of X. LAPACK will store the result in A. val A = lowerTriangular(X) val N = X.numRows val evs = DenseVector.zeros[Double](N) val lwork = math.max(1, 3*N-1) val work = Array.ofDim[Double](lwork) val info = new intW(0) LAPACK.getInstance.dsyev( if (rightEigenvectors) "V" else "N" /* eigenvalues N, eigenvalues & eigenvectors "V" */, "L" /* lower triangular */, N /* number of rows */, A.data, math.max(1, N) /* LDA */, evs.data, work /* workspace */, lwork /* workspace size */, info ) // A value of info.`val` < 0 would tell us that the i-th argument // of the call to dsyev was erroneous (where i == |info.`val`|). assert(info.`val` >= 0) if (info.`val` > 0) throw new NotConvergedException(NotConvergedException.Iterations) (evs, if (rightEigenvectors) Some(A) else None) } /** * Computes the LU factorization of the given real M-by-N matrix X such that * X = P * L * U where P is a permutation matrix (row exchanges). * * Upon completion, a tuple consisting of a matrix A and an integer array P. * * The upper triangular portion of A resembles U whereas the lower triangular portion of * A resembles L up to but not including the diagonal elements of L which are * all equal to 1. * * For 0 <= i < M, each element P(i) denotes whether row i of the matrix X * was exchanged with row P(i-1) during computation (the offset is caused by * the internal call to LAPACK). */ def LU[T](X: Matrix[T])(implicit td: T => Double): (DenseMatrix[Double], Array[Int]) = { requireNonEmptyMatrix(X) val M = X.numRows val N = X.numCols val Y = DenseMatrix.tabulate[Double](M,N)(X(_,_)) val ipiv = Array.ofDim[Int](math.min(M,N)) val info = new intW(0) LAPACK.getInstance.dgetrf( M /* numRows */, N /* numCols */, Y.data, math.max(1,M) /* LDA */, ipiv /* pivot indices */, info ) // A value of info.`val` < 0 would tell us that the i-th argument // of the call to dsyev was erroneous (where i == |info.`val`|). assert(info.`val` >= 0) (Y, ipiv) } /** * Computes the determinant of the given real matrix. */ def det[T](X: Matrix[T])(implicit td: T => Double): Double = { requireSquareMatrix(X) // For triangular N-by-N matrices X, the determinant of X equals the product // of the diagonal elements X(i,i) where 0 <= i < N. // Since det(AB) = det(A) * det(B), the LU factorization is well-suited for // the computation of the determinant of general N-by-N matrices. val (m, ipiv) = LU(X) // Count the number of exchanged rows. ipiv contains an array of swapped indices, // but it also contains indices that weren't swapped. To count the swapped // indices, we have to compare them against their position within the array. A // final complication is that the array indices are 1-based, due to the LU call // into LAPACK. val numExchangedRows = ipiv.map(_ - 1).zipWithIndex.count { piv => piv._1 != piv._2 } var acc = if (numExchangedRows % 2 == 1) -1.0 else 1.0 for (i <- 0 until m.numRows) acc *= m(i,i) acc } /** * Computes the inverse of a given real matrix. */ def inv[T](X: Matrix[T])(implicit td: T => Double): DenseMatrix[Double] = { requireSquareMatrix(X) val (m, ipiv) = LU(X) val N = m.numRows val lwork = math.max(1, N) val work = Array.ofDim[Double](lwork) val info = new intW(0) LAPACK.getInstance.dgetri( N, m.data, math.max(1, N) /* LDA */, ipiv, work /* workspace */, lwork /* workspace size */, info ) assert(info.`val` >= 0, "Malformed argument %d (LAPACK)".format(-info.`val`)) if (info.`val` > 0) throw new MatrixSingularException m } /** * Computes the Moore-Penrose pseudo inverse of the given real matrix X. */ def pinv(X: DenseMatrix[Double]) : DenseMatrix[Double] = { requireNonEmptyMatrix(X) // The pseudo inverse is nothing but the least-squares solution to AX=B, // hence: // d/dX 1/2 (AX-B)^2 = A^T (AX-B) // Solving A^T (AX-B) = 0 for X yields // A^T AX = A^T B // => X = (A^T A)^(-1) A^T B inv(X.t * X) * X.t } /** * Computes the Moore-Penrose pseudo inverse of the given real matrix X. */ def pinv[V](X: DenseMatrix[V])(implicit cast : V=>Double) : DenseMatrix[Double] = { requireNonEmptyMatrix(X) // The pseudo inverse is nothing but the least-squares solution to AX=B, // hence: // d/dX 1/2 (AX-B)^2 = A^T (AX-B) // Solving A^T (AX-B) = 0 for X yields // A^T AX = A^T B // => X = (A^T A)^(-1) A^T B pinv(X.mapValues(cast)); } /** * A diagonal matrix whose elements are specified by the given vector. */ def diag[S](v: scalala.tensor.Vector[S])(implicit s: Scalar[S]): DiagonalMatrix[Vector[S], S] = new DiagonalMatrix(v) /** * Vector cross product of 3D vectors a and b. */ def cross[V1, V2, RV](a: DenseVector[V1], b: DenseVector[V2])( implicit mul: BinaryOp[V1, V2, OpMul, RV], sub: BinaryOp[RV, RV, OpSub, RV], s: Scalar[RV] ): DenseVector[RV] = { require(a.length == 3) require(b.length == 3) DenseVector[RV]( sub(mul(a(1), b(2)), mul(a(2), b(1))), sub(mul(a(2), b(0)), mul(a(0), b(2))), sub(mul(a(0), b(1)), mul(a(1), b(0))) ) } /** * Computes the rank of a DenseMatrix[Double]. * * The rank of the matrix is computed using the SVD method. The singular values of the SVD * which are greater than a specified tolerance are counted. * * @param m matrix for which to compute the rank * @param tol optional tolerance for singular values. If not supplied, the default * tolerance is: max(m.numCols, m.numRows) * eps * sigma_max, where * eps is the machine epsilon and sigma_max is the largest singular value of m. * @return the rank of the matrix (number of singular values) */ def rank(m: DenseMatrix[Double], tol: Option[Double] = None): Int = { val (u, s, vt) = svd(m) val useTol = tol.getOrElse { // we called LAPACK for the SVD method, so this is the LAPACK definition of eps. val eps: Double = 2.0 * LAPACK.getInstance.dlamch("e") math.max(m.numCols, m.numRows) * eps * s.max } s.data.count(_ > useTol) // TODO: Use DenseVector[_].count() if/when that is implemented } } object LinearAlgebra extends LinearAlgebra; /** * Exception thrown if a routine has not converged. */ class NotConvergedException(val reason: NotConvergedException.Reason, msg: String = "") extends RuntimeException(msg) object NotConvergedException { trait Reason; object Iterations extends Reason; object Divergence extends Reason; object Breakdown extends Reason; } class MatrixNotSymmetricException extends IllegalArgumentException("Matrix is not symmetric"); class MatrixNotSquareException extends IllegalArgumentException("Matrix is not square"); class MatrixEmptyException extends IllegalArgumentException("Matrix is empty"); ================================================ FILE: src/main/scala/scalala/library/Numerics.scala ================================================ /* Copyright 2009 David Hall, Daniel Ramage 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. */ package scalala.library import math._ import scalala.tensor.Tensor1 /** * Provides some functions left out of java.lang.math. * * Borrowed from scalanlp. * * @author dlwh, afwlehmann */ trait Numerics { /** * The standard digamma function. Cribbed from Radford Neal * * http://google.com/codesearch/p?hl=en#EbB356_xxkI/fbm.2003-06-29/util/digamma.c */ def digamma(xx: Double) = { var x = xx; var r = 0.0; while (x<=5) { r -= 1/x; x += 1; } val f = 1d/(x * x); val t = f*(-1/12.0 + f*(1/120.0 + f*(-1/252.0 + f*(1/240.0 + f*(-1/132.0 + f*(691/32760.0 + f*(-1/12.0 + f*3617.0/8160.0))))))); r + log(x) - 0.5/x + t; } private val cof = Array(76.18009172947146, -86.50532032941677, 24.01409824083091,-1.231739572450155, 0.1208650973866179e-2,-0.5395239384953e-5 ); /** * Evaluates the log of the generalized beta function. * = \sum_a lgamma(c(a))- lgamma(c.sum) */ def lbeta[T](c: Tensor1[T,Double]) = { c.valuesIterator.foldLeft(-lgamma(c.sum))( (acc,x)=> acc +lgamma(x)); } /** * Computes the log of the gamma function. * * Reference: Numerical Recipes in C * http://www.library.cornell.edu/nr/cbookcpdf.html * www.cs.berkeley.edu/~milch/blog/versions/blog-0.1.3/blog/distrib * @return an approximation of the log of the Gamma function * of x. Laczos Approximation */ def lgamma(x : Double) = { var y = x; var tmp = x + 5.5; tmp -= ((x + 0.5) * log(tmp)); var ser = 1.000000000190015; var j = 0; while (j < 6) { y += 1; ser += (cof(j)/y); j +=1; } (-tmp + log(2.5066282746310005*ser / x)); } // erf and erfi: cribbed from http://en.wikipedia.org/wiki/Error_function private val erf_a = 0.147 /** * An approximation to the error function */ def erf(x: Double) = { val x2 = x*x val inner = exp(-1*x2*(4/Pi + erf_a*x2) / (1.0 + erf_a*x2)) signum(x)*sqrt(1.0 - inner) } def erfi(x: Double) = { val x2 = x*x val i1 = 2.0/(Pi*erf_a) + log(1-x2)/2.0 val i2 = log(1-x2)/erf_a signum(x) * sqrt( sqrt(i1*i1 - i2) - i1 ) } /** * Incomplete lgamma function. */ def lgamma(a: Double, z:Double) = { var res = 0d; var m = 21 while( m > 1) { res = ((1.0-m)*(m-1.0-a)) / (2*m -1+z -a + res); m -= 1 } a * log(z) - z - log(1+z-a+res); } /** * Incomplete gamma function, the exp of lgamma(a,z) */ def gamma(a: Double, z:Double) = exp(lgamma(a,z)); /** * Sums together things in log space. * @return log(exp(a) + exp(b)) */ def logSum(a: Double, b: Double) = { if (a.isNegInfinity) b else if (b.isNegInfinity) a else if (a < b) b + log1p(exp(a - b)) else a + log1p(exp(b - a)) } /** * Sums together things in log space. * @return log(\sum exp(a_i)) */ def logSum(a: Double, b: Double, c: Double*): Double = { if (c.length == 0) logSum(a, b) else logSum(logSum(a, b) +: c) } /** * Sums together things in log space. * @return log(\sum exp(a_i)) */ def logSum(iter: Iterator[Double], max: Double): Double = { require(iter.hasNext) if (max.isInfinite) { max } else { val aux = (0.0 /: iter) { (acc, x) => if (x.isNegInfinity) acc else acc + math.exp(x-max) } if (aux != 0) max + log(aux) else max } } /** * Sums together things in log space. * @return log(\sum exp(a_i)) */ def logSum(a: Seq[Double]): Double = { a.length match { case 0 => Double.NegativeInfinity case 1 => a(0) case 2 => logSum(a(0), a(1)) case _ => logSum(a.iterator, a reduceLeft (_ max _)) } } /** * Sums together the first length elements in log space. * The length parameter is used to make things faster. * * This method needs to be fast. Don't scala-ify it. * @return log(\sum^length exp(a_i)) */ def logSum(a: Array[Double], length: Int):Double = { length match { case 0 => Double.NegativeInfinity; case 1 => a(0) case 2 => logSum(a(0),a(1)); case _ => val m = max(a, length); if(m.isInfinite) m else { var i = 0; var accum = 0.0; while(i < length) { accum += exp(a(i) - m); i += 1; } m + log(accum); } } } // fast versions of max. Useful for the fast logsum. private def max(a: Array[Double], length: Int) = { var i = 1; var max = a(0); while(i < length) { if(a(i) > max) max = a(i); i += 1; } max; } /** * The sigmoid function: 1/(1 + exp(-x)); */ def sigmoid(x: Double) = 1/(1+exp(-x)); /** * Takes the difference of two doubles in log space. Requires a > b. * Note that this only works if a and b are close in value. For a >> b, * this will almost certainly do nothing. (exp(30) - exp(1) \approx exp(30)) * * @return log(exp(a) - exp(b)) */ def logDiff(a: Double, b: Double): Double = { require(a >= b) if (a > b) a + math.log(1.0 - math.exp(b-a)) else Double.NegativeInfinity } /** * Computes the polynomial P(x) with coefficients given in the passed in array. * coefs(i) is the coef for the x^i term. */ def poly(coefs: Array[Double], x: Double) = { var i = coefs.length-1; var p = coefs(i); while (i>0) { i -= 1; p = p*x + coefs(i); } p } } object Numerics extends Numerics ================================================ FILE: src/main/scala/scalala/library/Plotting.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; import generic.collection.{CanViewAsTensor1,CanViewAsTensor2}; import plotting._; import java.awt.Color; /** * Matlab-like plotting routines. * * @author dramage */ trait Plotting { /** Returns the default figure set. */ def figures = Figures.global; /** Selects and returns the requested figure by index (1-based). */ def figure(select:Int = -1)(implicit figures : Figures = figures) : Figure = { if (select >= 0) { figures.figure = select; figures.figure.refresh; } return figures.figure } /** Returns the current figure. */ def figure : Figure = figure(); /** Clears the current figure */ def clf()(implicit figure : Figure = figures.figure) = { figure.clear; } /** Returns the current plot in the current figure. */ def plot : XYPlot = figure.plot; /** Selects the given subplot. Note that select is 1-based for compatibility with matlab. */ def subplot(rows:Int,cols:Int,select:Int)(implicit figure : Figure = figure) : XYPlot = { figure.rows = rows; figure.cols = cols; figure.plot = select - 1; figure.refresh; return figure.plot; } /** Sets the title of this figure. */ def title(title : String)(implicit xyplot : XYPlot = plot) { xyplot.title = title; } /** Sets the label of the x axis */ def xlabel(text : String)(implicit xyplot : XYPlot = plot) { xyplot.xaxis.setLabel(text); } /** Sets the label of the y axis */ def ylabel(text : String)(implicit xyplot : XYPlot = plot) { xyplot.yaxis.setLabel(text); } /** Sets the lower and upper bounds of the current plot. */ def xlim(xmin : Double, xmax : Double)(implicit xyplot : XYPlot = figures.figure.plot) { xyplot.plot.getDomainAxis.setLowerBound(xmin); xyplot.plot.getDomainAxis.setUpperBound(xmax); } /** Sets the lower and upper bounds of the current plot. */ def ylim(ymin : Double, ymax : Double)(implicit xyplot : XYPlot = figures.figure.plot) { xyplot.plot.getRangeAxis.setLowerBound(ymin); xyplot.plot.getRangeAxis.setUpperBound(ymax); } /** For re-plotting to same figure */ def hold(state : Boolean)(implicit xyplot : XYPlot = figures.figure.plot) : Unit = { plot.hold = state; } /** Saves the current figure at the requested dpi to the given filename. */ def saveas(filename : String, dpi : Int = 72)(implicit figure : Figure = figure) : Unit = { // make sure figure is visible or saved image will come up empty figure.refresh(); plotting.ExportGraphics.writeFile( new java.io.File(filename), draw = figure.drawPlots _, width = figure.contents.getWidth, height = figure.contents.getHeight, dpi = dpi); } /** * Plots the given y versus the given x with the given style. * * @param x X-coordinates, co-indexed with y (and indexed by keys of type K). * @param y Y-coordinates, co-indexed with x (and indexed by keys of type K). * @param style Matlab-like style spec of the series to plot. * @param name Name of the series to show in the legend. * @param labels Optional in-graph labels for some points. * @param tips Optional mouse-over tooltips for some points. */ def plot[K,X,XV,Y,YV] (x : X, y : Y, style : Char = '-', colorcode : String = null, name : String = null, lines : Boolean = true, shapes : Boolean = false) // labels : PartialFunction[K,String] = null.asInstanceOf[PartialFunction[K,String]], // tips : PartialFunction[K,String] = null.asInstanceOf[PartialFunction[K,String]]) (implicit xyplot : XYPlot = figures.figure.plot, xtv : CanViewAsTensor1[X,K,XV], ytv : CanViewAsTensor1[Y,K,YV]) : Unit = { val series = xyplot.nextSeries; val xt = xtv(x); val yt = ytv(y); val labels : PartialFunction[K,String] = null; val tips : PartialFunction[K,String] = null; require(xt.domain == yt.domain, "x and y must have same domain"); val items = xt.domain.toIndexedSeq; // initialize dataset val dataset = XYDataset( items = items, name = if (name == null) "Series "+series else name, x = (k : K) => xt.scalar.toDouble(xt(k)), y = (k : K) => yt.scalar.toDouble(yt(k)), label = (k : K) => if (labels != null && labels.isDefinedAt(k)) labels(k) else null, tip = (k : K) => if (tips != null && tips.isDefinedAt(k)) tips(k) else null ); // initialize the series renderer val renderer = new org.jfree.chart.renderer.xy.XYLineAndShapeRenderer(); if (colorcode != null) { val color = PaintScale.convertToColor(colorcode); renderer.setSeriesPaint(0, color); renderer.setSeriesFillPaint(0, color); renderer.setSeriesOutlinePaint(0, color); } else { renderer.setSeriesPaint(0, XYPlot.paint(series)); renderer.setSeriesFillPaint(0, XYPlot.fillPaint(series)); renderer.setSeriesOutlinePaint(0, XYPlot.outlinePaint(series)); } renderer.setSeriesStroke(0, XYPlot.stroke(series)); renderer.setSeriesShape(0, XYPlot.shape(series)); renderer.setSeriesOutlineStroke(0, XYPlot.outlineStroke(series)); val tooltipGenerator = new org.jfree.chart.labels.XYToolTipGenerator() { override def generateToolTip(dataset : org.jfree.data.xy.XYDataset, series : Int, item : Int) : String = { dataset.asInstanceOf[XYDataset[_]].getTip(series, item); } } renderer.setSeriesToolTipGenerator(series, tooltipGenerator); val labelGenerator = new org.jfree.chart.labels.XYItemLabelGenerator() { override def generateLabel(dataset : org.jfree.data.xy.XYDataset, series : Int, item : Int) : String = { dataset.asInstanceOf[XYDataset[_]].getLabel(series, item); } } renderer.setSeriesItemLabelGenerator(series, labelGenerator); renderer.setSeriesItemLabelsVisible(series, labels != null); style match { case '-' => // default line type renderer.setSeriesLinesVisible(0,lines); renderer.setSeriesShapesVisible(0,shapes); case '.' => renderer.setSeriesLinesVisible(0,false); renderer.setSeriesShapesVisible(0,true); renderer.setSeriesShape(0,XYPlot.dot); case '+' => renderer.setSeriesLinesVisible(0,false); renderer.setSeriesShapesVisible(0,true); renderer.setSeriesShape(0,XYPlot.plus); case _ => throw new IllegalArgumentException("Expected style to be one of - . or +") } // set standard tick unit back to default (non-int) if we see non-ints if (!xt.scalar.zero.isInstanceOf[Int]) xyplot.setXAxisDecimalTickUnits(); if (!yt.scalar.zero.isInstanceOf[Int]) xyplot.setYAxisDecimalTickUnits(); // add dataset and renderer to plot xyplot.plot.setDataset(series, dataset); xyplot.plot.setRenderer(series, renderer); xyplot.refresh(); } /** * Displays a scatter plot of x versus y, each point drawn at the given * size and mapped with the given color. * * Example usage: https://gist.github.com/1288473 * * @param x The x coordinates to draw as provided by anything that can be seen as a Tensor1. * @param y The y coordinates to draw as provided by anything that can be seen as a Tensor1. * @param s The size of each circle (on the same scale as the domain axis); * @param c A partial function (e.g. a Map) from item ids to the color to draw the bubble. * Missing colors are drawn with a hashed pattern. * @param labels Labels to draw next to each point. * @param tips Tooltips to show on mouseover for each point. * @param name Series name for legend */ def scatter[K,X,XV,Y,YV,S,SV] (x : X, y : Y, size : S, colors : PartialFunction[K,java.awt.Paint], labels : PartialFunction[K,String] = null.asInstanceOf[PartialFunction[K,String]], tips : PartialFunction[K,String] = null.asInstanceOf[PartialFunction[K,String]], name : String = null) (implicit xyplot : XYPlot = figures.figure.plot, xtv : CanViewAsTensor1[X,K,XV], ytv : CanViewAsTensor1[Y,K,YV], stv : CanViewAsTensor1[S,K,SV]) : Unit = { val series = xyplot.nextSeries; val (xt,yt,st) = (xtv(x), ytv(y), stv(size)); require(xt.domain == yt.domain, "x and y must have same domain"); val items = xt.domain.toIndexedSeq; val paintScale = CategoricalPaintScale[K](colors); // initialize dataset val dataset = XYZDataset( items = items, name = if (name == null) "Series "+series else name, x = (k : K) => xt.scalar.toDouble(xt(k)), y = (k : K) => yt.scalar.toDouble(yt(k)), z = (k : K) => st.scalar.toDouble(st(k)), label = (k : K) => if (labels != null && labels.isDefinedAt(k)) labels(k) else null, tip = (k : K) => if (tips != null && tips.isDefinedAt(k)) tips(k) else null ); // initialize the series renderer import org.jfree.chart.renderer.xy.XYBubbleRenderer; val renderer = new XYBubbleRenderer(XYBubbleRenderer.SCALE_ON_DOMAIN_AXIS) {; val stroke = new java.awt.BasicStroke(0f); override def getItemPaint(series : Int, item : Int) : java.awt.Paint = paintScale(items(item)); override def getItemStroke(series : Int, item : Int) = stroke; } val tooltipGenerator = new org.jfree.chart.labels.XYToolTipGenerator() { override def generateToolTip(dataset : org.jfree.data.xy.XYDataset, series : Int, item : Int) : String = { dataset.asInstanceOf[XYZDataset[_]].getTip(0, item); } } renderer.setSeriesToolTipGenerator(series, tooltipGenerator); val labelGenerator = new org.jfree.chart.labels.BubbleXYItemLabelGenerator() { override def generateLabel(dataset : org.jfree.data.xy.XYDataset, series : Int, item : Int) : String = { dataset.asInstanceOf[XYZDataset[_]].getLabel(0, item); } } renderer.setSeriesItemLabelGenerator(series, labelGenerator); renderer.setSeriesItemLabelsVisible(series, labels != null); // set standard tick unit back to default (non-int) if we see non-ints if (!xt.scalar.zero.isInstanceOf[Int]) xyplot.setXAxisDecimalTickUnits(); if (!yt.scalar.zero.isInstanceOf[Int]) xyplot.setYAxisDecimalTickUnits(); // add dataset and renderer to plot xyplot.plot.setDataset(series, dataset); xyplot.plot.setRenderer(series, renderer); xyplot.refresh(); } // /** An XY stacked area chart. */ // def stacked(x : Vector, y : Seq[Vector], names : Seq[String])(implicit xyplot : XYPlot = _figures.figure.plot) { // import org.jfree.data.xy.{AbstractXYDataset, TableXYDataset}; // val dataset = new AbstractXYDataset with TableXYDataset { // override def getX(series : Int, item : Int) = x(item); // override def getY(series : Int, item : Int) = y(series)(item); // override def getSeriesKey(series : Int) = names(series); // override def getSeriesCount = y.size; // override def getItemCount = x.size; // override def getItemCount(series : Int) = y(series).size; // }; // // import org.jfree.chart.renderer.xy.StackedXYAreaRenderer2; // // val renderer = new StackedXYAreaRenderer2(null,null); // renderer.setOutline(true); // // // add dataset and renderer // val series = xyplot.nextSeries; // xyplot.plot.setDataset(series,dataset); // xyplot.plot.setRenderer(series, renderer); // xyplot.refresh; // } // // /** An XY stacked area chart with default names. */ // def stacked(x : Vector, y : Seq[Vector])(implicit xyplot : XYPlot = _figures.figure.plot) { // stacked(x, y, y.iterator.zipWithIndex.map(_._2.toString).toSeq)(xyplot); // } /** Plots a histogram of the given data into the given number of bins */ def hist[D,K,V](data : D, bins : HistogramBins = 10, name : String = "Histogram") (implicit xyplot : XYPlot = plot, dtv : CanViewAsTensor1[D,K,V]) : Unit = { val dt = dtv(data); implicit def dvToDouble(v : V) = dt.scalar.toDouble(v); val binner : StaticHistogramBins = bins match { case static : StaticHistogramBins => static; case dynamic : DynamicHistogramBins => dynamic(dt.min, dt.max); } val counts = new Array[Int](binner.splits.length + 1); for (value <- dt.valuesIterator) { counts(binner.bin(value)) += 1; } val width = (binner.splits.iterator zip binner.splits.iterator.drop(1)).map(tup => tup._2 - tup._1).min; val dataset = new org.jfree.data.xy.XYBarDataset( XYDataset( name = name, items = IndexedSeq.range(0,counts.length), x = (i : Int) => if (i == binner.splits.length) { binner.splits(i - 1) + width / 2.0 } else { binner.splits(i) - width / 2.0 }, y = (i : Int) => counts(i), label = (i : Int) => null, tip = (i : Int) => null ), width); val series = xyplot.nextSeries; val renderer = new org.jfree.chart.renderer.xy.XYBarRenderer; renderer.setSeriesPaint(0, XYPlot.paint(series)); renderer.setSeriesShape(0, XYPlot.shape(series)); renderer.setSeriesStroke(0, XYPlot.stroke(series)); renderer.setSeriesFillPaint(0, XYPlot.fillPaint(series)); renderer.setSeriesOutlinePaint(0, XYPlot.outlinePaint(series)); renderer.setSeriesOutlineStroke(0, XYPlot.outlineStroke(series)); renderer.setShadowVisible(false); renderer.setBarPainter(new org.jfree.chart.renderer.xy.StandardXYBarPainter()); xyplot.plot.getDomainAxis.setLowerBound(binner.splits(0)-width/2.0); xyplot.plot.getDomainAxis.setUpperBound(binner.splits(binner.splits.length-1)+width/2.0); // set standard tick unit back to default (non-int) xyplot.setXAxisDecimalTickUnits(); xyplot.setYAxisDecimalTickUnits(); xyplot.plot.setDataset(series,dataset); xyplot.plot.setRenderer(series,renderer); xyplot.refresh(); } /** * Displays an image in the current figure, where each cell in the matrix * provides color for one square of the image. * * @param img A matrix containing the colors to plot * @param scale Scale used for converting matrix values to colors. * @param showScale If true, show the paint scale legend * @param name Series name * @param offset Offset for indexing the top-left corner of the matrix * @param labels Labels for some subset of the data points * @param tips Tooltip popups for some subset of the data points */ def image[M,V] (img : M, scale : GradientPaintScale[Double] = null, showScale : Boolean = true, name : String = null, offset : (Int,Int) = (0,0), labels : PartialFunction[(Int,Int), String] = null.asInstanceOf[PartialFunction[(Int,Int), String]], tips : PartialFunction[(Int,Int), String] = null.asInstanceOf[PartialFunction[(Int,Int), String]]) (implicit xyplot : XYPlot = figures.figure.plot, mtv : CanViewAsTensor2[M,Int,Int,V]) { val mt = mtv(img); val series = xyplot.nextSeries; val domain = mt.domain; val (minx,maxx) = (domain._2.min, domain._2.max); val (miny,maxy) = (domain._1.min, domain._1.max); val items = domain.toIndexedSeq; // initialize dataset val dataset = XYZDataset( items = items, name = if (name == null) "Series "+series else name, x = (k : (Int,Int)) => k._2 + offset._2, y = (k : (Int,Int)) => k._1 + offset._1, z = (k : (Int,Int)) => mt.scalar.toDouble(mt(k._1, k._2)), label = (k : (Int,Int)) => if (labels != null && labels.isDefinedAt(k)) labels(k) else null, tip = (k : (Int,Int)) => if (tips != null && tips.isDefinedAt(k)) tips(k) else null ); // initialize renderer import org.jfree.chart.renderer.xy.XYBlockRenderer val renderer = new XYBlockRenderer(); renderer.setSeriesPaint(0, XYPlot.paint(series)); renderer.setSeriesShape(0, XYPlot.shape(series)); renderer.setSeriesStroke(0, XYPlot.stroke(series)); renderer.setSeriesFillPaint(0, XYPlot.fillPaint(series)); renderer.setSeriesOutlinePaint(0, XYPlot.outlinePaint(series)); renderer.setSeriesOutlineStroke(0, XYPlot.outlineStroke(series)); val tooltipGenerator = new org.jfree.chart.labels.XYToolTipGenerator() { override def generateToolTip(dataset : org.jfree.data.xy.XYDataset, series : Int, item : Int) : String = { dataset.asInstanceOf[XYZDataset[_]].getTip(series, item); } } renderer.setSeriesToolTipGenerator(series, tooltipGenerator); val labelGenerator = new org.jfree.chart.labels.XYItemLabelGenerator() { override def generateLabel(dataset : org.jfree.data.xy.XYDataset, series : Int, item : Int) : String = { dataset.asInstanceOf[XYZDataset[_]].getLabel(series, item); } } renderer.setSeriesItemLabelGenerator(series, labelGenerator); renderer.setSeriesItemLabelsVisible(series, labels != null); val staticScale = { if (scale == null) GradientPaintScaleFactory[Double]().apply(mt.values.toList.map(mt.scalar.toDouble)).asInstanceOf[GradientPaintScale[Double]] else scale } // val staticScale : StaticPaintScale = scale match { // case static : StaticPaintScale => // static; // // case dynamic : DynamicPaintScale => { // val values = items.view.map(item => // mt.scalar.toDouble(mt(item._1, item._2))).filter(!_.isNaN); // if (values.isEmpty) { // dynamic(lower = Double.NaN, upper = Double.NaN); // } else { // dynamic(lower = values.min, upper = values.max); // } // } // } val paintScale = new org.jfree.chart.renderer.PaintScale { override def getLowerBound = staticScale.lower; override def getUpperBound = staticScale.upper; override def getPaint(value : Double) = staticScale(value); } renderer.setPaintScale(paintScale); renderer.setBlockAnchor(org.jfree.ui.RectangleAnchor.BOTTOM_LEFT); renderer.setBlockWidth(1); renderer.setBlockHeight(1); xyplot.plot.getRangeAxis.setInverted(true); xyplot.plot.getRangeAxis.setLowerBound(miny+offset._2); xyplot.plot.getRangeAxis.setUpperBound(maxy+1+offset._2); xyplot.plot.getRangeAxis.setStandardTickUnits(XYPlot.integerTickUnits); xyplot.plot.getDomainAxis.setLowerBound(minx+offset._1); xyplot.plot.getDomainAxis.setUpperBound(maxx+1+offset._1); xyplot.plot.getDomainAxis.setStandardTickUnits(XYPlot.integerTickUnits); // set legend if (showScale) { val legendAxis = new org.jfree.chart.axis.NumberAxis(); legendAxis.setLowerBound(staticScale.lower); legendAxis.setUpperBound(staticScale.upper); val legend = new org.jfree.chart.title.PaintScaleLegend(paintScale, legendAxis); import org.jfree.chart.title._; import org.jfree.ui._; import org.jfree.chart.block._; legend.setMargin(new RectangleInsets(40, 2, 40, 2)); legend.setPadding(new RectangleInsets(10, 2, 10, 2)); legend.setBorder(1,1,1,1); legend.setBackgroundPaint(Color.white); legend.setPosition(RectangleEdge.RIGHT); xyplot.chart.addSubtitle(legend); } // add dataset and renderer to plot xyplot.plot.setDataset(series, dataset); xyplot.plot.setRenderer(series, renderer); xyplot.refresh(); } } /** * An object with access to the Plotting trait members. * * @author dramage */ object Plotting extends Plotting { } ================================================ FILE: src/main/scala/scalala/library/Random.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; import random.MersenneTwisterFast /** *

Random number generation. This class uses the MersenneTwisterFast * implementation by Sean Luke http://www.cs.gmu.edu/~sean/research/ * as its underlying random number generator. The Mersenne Twister * is very fast with an excellent pseudo-random distribution, but it * is not cryptographically strong.

* *

Each random number generating method accepts a * MersenneTwisterFast implementation as an implicit argument, defaulting * to the Random.mt instance. That instance's seed is set * with the long value held in the scalala.library.random.seed System property. * If the property is not defined, the current time in milliseconds is used * as the random seed.

* *

The MersenneTwisterFast implementation is not thread-safe, so all * accessors to an instance (mt) wrap calls in a mt.synchronized * block. Therefore, calling a vector constructor is substantially faster * than calling rand() many times.

* *

The seed can be set with the system property during Java invocation, e.g. by * -Dscalala.library.random.seed=1l

* * @author dramage,afwlehmann */ object Random { /** * Returns a pseudo-random number from [0,1). */ def rand()(implicit mt: MersenneTwisterFast): Double = mt.synchronized { mt.nextDouble() } /** * Returns a pseudo-random gaussian variable. * */ def randn()(implicit mt: MersenneTwisterFast) = mt.synchronized { mt.nextGaussian() } /** * Returns a pseudo-random integer between 0 (incl.) and `max` (excl.). */ def randi(max: Int)(implicit mt: MersenneTwisterFast) = mt.synchronized { mt.nextInt(max) } lazy val seed : Long = { val prop = System.getProperty("scalala.library.random.seed"); if (prop != null) prop.toLong else System.currentTimeMillis; } implicit val mt : MersenneTwisterFast = new MersenneTwisterFast(seed); } ================================================ FILE: src/main/scala/scalala/library/Statistics.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; import math._ import Numerics._ import operators.Implicits._ import generic.collection.{CanViewAsVector,CanViewAsTensor1} /** * Matlab-like statistical methods. * * @author dramage,afwlehmann */ trait Statistics { private val sqrt2 = sqrt(2); /** * Computes the cumulative density function of the value x. */ def normcdf(x: Double, mu : Double = 0.0, sigma : Double = 1.0) = .5 * (1 + erf((x - mu) / sqrt2 / sigma)); /** * Computes the Pearson correlation coefficient between two objects that * can be viewed as Tensor1 instances (such as arrays, vectors, counters) * with values that can be viewed as doubles. * * Code adapted excerpted from Wikipedia: * http://en.wikipedia.org/wiki/Pearson%27s_correlation_coefficient */ def corrcoef[K,X,VX,Y,VY](x : X, y : Y) (implicit xvt : CanViewAsTensor1[X,K,VX], yvt : CanViewAsTensor1[Y,K,VY], vx : VX => Double, vy : VY => Double) : Double = { // tensor view of x and y val xt = xvt(x); val yt = yvt(y); val N = xt.size; var sum_sq_x = 0.0; var sum_sq_y = 0.0; var sum_coproduct = 0.0; var mean_x = 0.0; var mean_y = 0.0; var i = 0; (xt joinAll yt) { (k : K, xv : VX, yv : VY) => val sweep = i / (i + 1.0); val delta_x = xv - mean_x; val delta_y = yv - mean_y; sum_sq_x += (delta_x * delta_x * sweep); sum_sq_y += (delta_y * delta_y * sweep); sum_coproduct += (delta_x * delta_y * sweep); i += 1; mean_x += (delta_x / i); mean_y += (delta_y / i); } val pop_sd_x = math.sqrt(sum_sq_x / N); val pop_sd_y = math.sqrt(sum_sq_y / N); val cov_x_y = sum_coproduct / N; return cov_x_y / (pop_sd_x * pop_sd_y); } /** * Computes Kendall's Tau correlation coefficient between the two vectors * x and y. The measure is a correlation based on ranks, essentially counting * the number of concordant minus discordant pairs, normalized by the number * of pairs. Breaking ties is tricky and important. See: * * "A modification of Kendall's Tau for the case of arbitrary ties in both * rankings" by L. M. Adler, 1957. http://www.jstor.org/stable/2281397?seq=1 */ def kendall[X,XV,Y,YV](x : X, y : Y) (implicit xvt : CanViewAsVector[X,XV], yvt : CanViewAsVector[Y,YV]) : Double = { val _x = xvt(x); @inline implicit def xvtod(v : XV) = _x.scalar.toDouble(v); val _y = yvt(y); @inline implicit def yvtod(v : YV) = _y.scalar.toDouble(v); require(_x.size == _y.size, "Vectors must have same length"); val N = _x.size; if (N == 0) { return Double.NaN; } // keep track of ties in x and in y val xties = new scala.collection.mutable.HashMap[Double,scala.collection.mutable.HashSet[Int]]; val yties = new scala.collection.mutable.HashMap[Double,scala.collection.mutable.HashSet[Int]]; var numer = 0.0; for (i <- 0 until N; j <- 0 until i) { if (_x(i) == _x(j)) { val s = xties.getOrElseUpdate(_x(i), new scala.collection.mutable.HashSet[Int]); s += i; s += j; } if (_y(i) == _y(j)) { val s = yties.getOrElseUpdate(_y(i), new scala.collection.mutable.HashSet[Int]); s += i; s += j; } numer += math.signum(_x(i) - _x(j)) * math.signum(_y(i) - _y(j)); } var denom = N * (N - 1.0) / 2.0; var xdenom = xties.valuesIterator.map(s => s.size * (s.size - 1.0)).sum / 2.0; var ydenom = yties.valuesIterator.map(s => s.size * (s.size - 1.0)).sum / 2.0; return numer / math.sqrt((denom - xdenom) * (denom - ydenom)); } // def mannwhitneyu(a : Seq[Double], b : Seq[Double]) = { // val merged = (a.map(_ -> 'a') ++ b.map(_ -> 'b')).sortWith(_._1 < _._1); // val ranked = ranks(merged.toArray.map(_._1)); // val aU = (for ((v,r) <- (merged.iterator zip ranked.iterator); if v._2 == 'a') yield r).sum - (a.size * (a.size + 1) / 2); // val bU = (for ((v,r) <- (merged.iterator zip ranked.iterator); if v._2 == 'b') yield r).sum - (b.size * (b.size + 1) / 2); // val (bigU,smallU) = if (aU > bU) (aU,bU) else (bU,aU); // val sd = math.sqrt(a.size * b.size * (a.size + b.size + 1) / 12.0); // (aU, normcdf(-abs((bigU - a.size * b.size / 2.0) / sd))); // } /** Returns n choose k, how many ways to pick k objects from n. */ def nchoosek(n : Int, k : Int) : Long = { var aa = 0.0; var ai = k+1; while (ai <= n) aa += math.log(ai); var bb = 0.0; var bi = 2; while (bi <= n-k) bb += math.log(bi); math.exp(aa - bb).round; } /** Returns n factorial, the number of orderings of n objects. */ def factorial(n : Int) : Long = { var i = n; var rv = 1l; while (i > 1) { rv *= i; i -= 1; } rv; } /** * Returns the cumulative distribution function of the binomial evaluated * at x; i.e. returns the probability that at most x draws out of n draws * of a binomial with paramater p come up heads. */ def binomialCDF(n:Int,p:Double)(x:Int) = { var rv = 0.0; var i = 0; while (i < x) { rv += nchoosek(n,i) * math.pow(p,i) * math.pow(1-p,n-i); i += 1; } rv; } } /** * An object with access to the Statistics trait members. * * @author dramage */ object Statistics extends Statistics { } ================================================ FILE: src/main/scala/scalala/library/Storage.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.library import scalala.tensor.{::, Matrix} import scalala.tensor.dense.DenseMatrix import java.io._ import util.matching.Regex trait Storage { /** * Deserializes a DenseMatrix from the given input stream. * * @param is * the input stream * @param skipRows * number of lines to skip at the beginning * @param columns * indices of the columns to be used, or null for all columns (default), e.g. * List(1,3) for columns 2 and 4, respectively * @param delimiter * a regular expression defining the delimiter that is used to separate the * values * @param comments * a regular expression defining the start of comments which will be removed * throughout the process */ def loadtxt(is: InputStream, skipRows: Int = 0, columns: Seq[Int] = null, delimiter: Regex = Storage.defaultDelimiter, comments: Regex = Storage.defaultComments): DenseMatrix[Double] = { require(skipRows >= 0) require(columns == null || columns.size > 0) val it = new Iterator[Array[String]] { val br = new BufferedReader(new InputStreamReader(is)) def hasNext = br.ready def next = // Regex.split actually returns an Array("") in case of an empty // input string yet we want Array.empty instead, thus: delimiter split (comments replaceFirstIn (br.readLine, "") trim) match { case Array("") => Array.empty[String] case r => r } } for (i <- 0 until skipRows if it.hasNext) { it.next() } var numCols = -1 val rows: Array[Array[Double]] = (for (tokens <- it if !tokens.isEmpty) yield { if (tokens.size != numCols) { if (numCols == -1) numCols = tokens.size else throw new RuntimeException("All lines must have the same number of columns!") } if (columns == null) tokens.map(_.toDouble).toArray[Double] else ((for (colIdx <- columns) yield tokens(colIdx).toDouble)).toArray[Double] }).toArray if (rows.size > 0) DenseMatrix(rows:_*) else null } /** * Serializes the given matrix to the given output stream. The given delimiter * is used to separate the values of each row. */ def storetxt(os: OutputStream, m: Matrix[Double], delimiter: String = "\t") { val bw = new BufferedWriter(new OutputStreamWriter(os)) for (i <- 0 until m.numRows) { bw.write(m(i,::).values.iterator map ("%.15e".format(_)) mkString delimiter) bw.newLine() } bw.flush() } } object Storage extends Storage { val defaultDelimiter: Regex = """\s+""".r val defaultComments: Regex = """#.*$""".r } ================================================ FILE: src/main/scala/scalala/library/plotting/Dataset.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; package plotting; import scala.collection.mutable.ArrayBuffer; /** * An XY dataset consisting of some number of named series, each consisting * of items of type Item, with an associated x value, y value, and optionally * a name and tooltip. * * @author dramage */ class XYDataset[Item](x : Item=>Number, y : Item=>Number, label : Item=>String, tip : Item=>String) extends org.jfree.data.xy.AbstractXYDataset { val names = ArrayBuffer[String](); val items = ArrayBuffer[IndexedSeq[Item]](); override def getSeriesKey(series : Int) = names(series); override def getSeriesCount = names.length; override def getItemCount(series : Int) = items(series).length; override def getX(series : Int, item : Int) : Number = x(items(series)(item)); override def getY(series : Int, item : Int) : Number = y(items(series)(item)); def getLabel(series : Int, item : Int) : String = label(items(series)(item)); def getTip(series : Int, item : Int) : String = tip(items(series)(item)); } object XYDataset { def apply[Item](name : String, items : IndexedSeq[Item], x : Item=>Number, y : Item=>Number, label : Item=>String, tip : Item=>String) : XYDataset[Item] = { val rv = new XYDataset(x, y, label, tip); rv.names += name; rv.items += items; rv; } } /** * An XYX dataset consisting of some number of named series, each consisting * of items of type Item, with an associated x value, y value, z value, * and optionally a name and tooltip. * * @author dramage */ class XYZDataset[Item](x : Item=>Number, y : Item=>Number, z : Item=>Number, label : Item=>String, tip : Item=>String) extends org.jfree.data.xy.AbstractXYZDataset { val names = ArrayBuffer[String](); val items = ArrayBuffer[IndexedSeq[Item]](); override def getSeriesKey(series : Int) = names(series); override def getSeriesCount = names.length; override def getItemCount(series : Int) = items(series).length; override def getX(series : Int, item : Int) : Number = x(items(series)(item)); override def getY(series : Int, item : Int) : Number = y(items(series)(item)); override def getZ(series : Int, item : Int) : Number = z(items(series)(item)); def getLabel(series : Int, item : Int) : String = label(items(series)(item)); def getTip(series : Int, item : Int) : String = tip(items(series)(item)); } object XYZDataset { def apply[Item](name : String, items : IndexedSeq[Item], x : Item=>Number, y : Item=>Number, z : Item=>Number, label : Item=>String, tip : Item=>String) : XYZDataset[Item] = { val rv = new XYZDataset(x, y, z, label, tip); rv.names += name; rv.items += items; rv; } } ================================================ FILE: src/main/scala/scalala/library/plotting/ExportGraphics.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; package plotting; import java.io.{File,OutputStream,FileOutputStream,IOException}; import java.awt.Graphics2D; /** * Utility functions for exporting a Graphics2D drawable to some eps, pdf, * and png. * * @author dramage, Robby McKilliam */ object ExportGraphics { /** A Drawable is any function that draws to a Graphics2D context. */ type Drawable = ((Graphics2D)=>Unit); /** * Writes the given drawable to a new file of the given name with * the given dpi (for rasterized formats only). The extension of the file * determines its format, with options png, eps, svg, and pdf. */ def writeFile(file : File, draw : Drawable, width : Int, height : Int, dpi : Int = 72) = { lazy val fos = new FileOutputStream(file); if (file.getName.toLowerCase.endsWith(".png")) { try { writePNG(fos,draw,width,height,dpi); } finally { fos.close(); } } else if (file.getName.toLowerCase.endsWith(".eps")) { try { writeEPS(fos,draw,width,height); } finally { fos.close(); } } else if (file.getName.toLowerCase.endsWith(".pdf")) { try { writePDF(fos,draw,width,height); } finally { fos.close(); } // } else if (file.getName.toLowerCase.endsWith(".svg")) { // try { // writeSVG(fos,draw,width,height); // } finally { // fos.close(); // } } else { throw new IOException("Unrecognized file extension: should be png, svg, eps, or pdf"); } } /** * Writes the given drawable to the given OutputStream at the given dpi, * formatted as png. */ def writePNG(out : OutputStream, draw : Drawable, width : Int, height : Int, dpi : Int = 72) { import javax.imageio.ImageIO; import java.awt.image.BufferedImage; // default dpi is 72 val scale = dpi / 72.0; val swidth = (width * scale).toInt; val sheight = (height * scale).toInt; val image = new BufferedImage(swidth,sheight,BufferedImage.TYPE_INT_ARGB); val g2d = image.createGraphics(); g2d.scale(scale, scale); draw(g2d); g2d.dispose; ImageIO.write(image, "png", out); } /** * Writes the given drawable to the given OutputStream formatted as eps. */ def writeEPS(out : OutputStream, draw : Drawable, width : Int, height : Int) { import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; val g2d = new EPSDocumentGraphics2D(false); g2d.setGraphicContext(new GraphicContext); g2d.setupDocument(out, width, height); draw(g2d); g2d.finish(); } /** * Writes the given drawable to the given OutputStream formatted as pdf. * Contributed by Robby McKilliam. */ def writePDF(out : OutputStream, draw : Drawable, width : Int, height : Int) { import com.lowagie.text.Document; import com.lowagie.text.Rectangle; import com.lowagie.text.pdf.PdfWriter; val document = new Document(); try { document.setPageSize(new Rectangle(width, height)); val writer = PdfWriter.getInstance(document, out); document.open(); val cb = writer.getDirectContent(); val tp = cb.createTemplate(width, height); val g2d = tp.createGraphics(width, height); draw(g2d); g2d.dispose; cb.addTemplate(tp, 1, 0, 0, 1, 0, 0); } finally { document.close(); } } // /** // * Writes the given drawable to the given OutputStream formatted as svg. // */ // def writeSVG(out : OutputStream, draw : Drawable, width : Int, height : Int) { // import org.apache.batik.svggen.SVGGraphics2D; // import org.apache.batik.dom.GenericDOMImplementation; // import org.w3c.dom.Document; // import java.io.OutputStreamWriter; // // val dom = GenericDOMImplementation.getDOMImplementation(); // val document = dom.createDocument("http://www.w3.org/2000/svg","svg",null); // val g2d = new SVGGraphics2D(document); // draw(g2d); // g2d.stream(new OutputStreamWriter(out, "UTF-8"), true); // g2d.dispose(); // } } ================================================ FILE: src/main/scala/scalala/library/plotting/Figure.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; package plotting; import scala.collection.mutable.ArrayBuffer; import javax.swing.JFrame; import javax.swing.JPanel; import java.awt.Graphics2D; import javax.swing.WindowConstants; /** A Figure holds a collection of XYPlot instances */ class Figure(figures : Figures) { /** List of plots in the figure. */ protected val plots = ArrayBuffer[Option[XYPlot]](); /** How many rows of plots are in the figure */ private var rows_ = 1; def rows = rows_; def rows_=(newrows : Int) : Unit = { rows_ = newrows; refresh(); } /** How many cols of plots are in the figure */ private var cols_ = 1 ; def cols = cols_; def cols_=(newcols : Int) : Unit = { cols_ = newcols; refresh(); } /** Visibility state of the plot */ private var visible_ = true; def visible = visible_; def visible_=(newvis : Boolean) : Unit = { visible_ = newvis; frame.setVisible(visible_); } /** JPanel holding for drawing subplots in this figure. */ val contents = { val _c = new JPanel(); _c.setSize(600,400); _c; } /** The Swing frame for this plot */ lazy val frame : JFrame = { val f = new JFrame("Figure "+(figures.number(this))); f.setSize(600,400); f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); f.setLayout(new java.awt.BorderLayout()); f.add(contents, java.awt.BorderLayout.CENTER); // we use visible_ to avoid an infinite loop f.setVisible(visible_); f } /** Returns the number of the given plot in this container */ def number(plot : XYPlot) : Int = plots.indexOf(plot); private var plot_ = 0; /** Returns the current plot in the figure */ def plot : XYPlot = plots(plot_).get; /** Uses the given plot number. */ def plot_=(number : Int) : Unit = { assert(number >= 0, "Plot number must be non-negative"); while (plots.length <= number) { plots += None; } if (plots(number) == None) { plots(number) = Some(new XYPlot(this)); } plot_ = number; } // create the initial plot (don't call clear lest we pop up a window) plot = 0; /** Clears the current plot */ def clear() { contents.removeAll(); plots.clear(); plot = 0; rows = 1; cols = 1; refresh(); } /** Redraws the figure */ def refresh() : Unit = { while (plots.length < rows * cols) { plots += None; } while (plots.length > rows * cols) { plots.remove(plots.length-1); } contents.removeAll; contents.setLayout(new java.awt.GridLayout(rows,cols)); for (plot <- plots) { contents.add(plot match { case Some(plot) => plot.panel; case None => new JPanel() }); } frame.repaint(); frame.setVisible(visible); } def drawPlots(g2d : Graphics2D) { val plotWidth = contents.getWidth / cols; val plotHeight = contents.getHeight / rows; var px = 0; var py = 0; for (opt <- plots) { opt match { case Some(plot) => plot.chart.draw(g2d, new java.awt.Rectangle(px*plotWidth, py*plotHeight, plotWidth, plotHeight)); case None => {} } px = (px +1)%cols; if(px == 0) py = (py + 1)%rows; } } } ================================================ FILE: src/main/scala/scalala/library/plotting/Figures.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; package plotting; import scala.collection.mutable.ArrayBuffer; /** Class that holds a collection of Figure instances */ class Figures { private val figures = ArrayBuffer[Option[Figure]](); /** Returns the number of the given figure */ def number(figure : Figure) : Int = figures.indexOf(Some(figure)); /** Returns the current figure. Defaults to 1, but allows 0. */ var figure_ : Int = 1; def figure : Figure = figures(figure_).get; def figure_=(number : Int) : Unit = { while (figures.length <= number) { figures += None; } if (figures(number) == None) { figures(number) = Some(new Figure(this)); } figure_ = number; } /** Returns the current figure's current plot */ def plot : XYPlot = figure.plot; // Set the current figure to figure 1 figure = 1; } object Figures { lazy val global = new Figures(); } ================================================ FILE: src/main/scala/scalala/library/plotting/HistogramBins.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; package plotting; import scalala.generic.collection.CanViewAsTensor1; /** * Bins for a histogram. These can be implicitly constructed from: *
 *   x : HistogramBins = 10  // 10 dynamically determined histogram bins
 *   x : HistogramBins = Array(1.0,2.0,3.2) // five buckets wit the given splits
 *   x : HistogramBins = (0,100,10) // ten bins evenly dividing 0 to 100.
 * 
* * @author dramage */ sealed trait HistogramBins; /** * Set of histograms for binning data using the given splits. * * @author dramage */ case class StaticHistogramBins(splits : Array[Double]) extends HistogramBins { /** Returns the bin for the given value, between 0 and splits.length inclusive. */ def bin(value : Double) = { var i = 0; while (i < splits.length && value > splits(i)) { i += 1; } i; } } /** * Create a set of StaticHistogramBins from a number and an (eventual) * lower and upper bound. * * @author dramage */ case class DynamicHistogramBins(number : Int = 10) extends HistogramBins { def apply(lower : Double, upper : Double) = StaticHistogramBins(Array.tabulate(number-1)(i => lower + ((i + 1.0) / (number)) * (upper - lower))); } /** * Static constructors for HistogramBins. * * @author dramage */ object HistogramBins { implicit def fromNumber(number : Int) : HistogramBins = DynamicHistogramBins(number); // implicit def fromSplits[S,K,V](splits : S)(implicit tt : CanViewAsTensor1[S,K,V], v : V=>Double) : HistogramBins = // StaticHistogramBins(t.domain(splits).map(d => v(t.get(splits, d))).toArray); implicit def fromRange(minMaxCount : (Double,Double,Int)) : HistogramBins = DynamicHistogramBins(minMaxCount._3)(minMaxCount._1, minMaxCount._2); } ================================================ FILE: src/main/scala/scalala/library/plotting/PaintScale.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; package plotting; import java.awt.{Color,Paint,TexturePaint}; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; /** * Maps items of type T to a well defined Paint (usually a color). * * An implicit conversion exists to make a singleton PaintScaleFactory from * a PaintScale instance, which means that PaintScales can be provided * directly whenever a PaintScaleFactory is required. * * @author dramage */ sealed trait PaintScale[T] extends (T => Paint); /** * A simple numeric paint scale for mapping a number within a range to a * corresponding element of a pre-computed color gradient. Colors from the * given gradient array are used linearly to represent values between * lower and upper. * * @author dramage */ case class GradientPaintScale[T] (lower : T, upper : T, gradient : Array[Color] = PaintScale.WhiteToBlack) (implicit view : T=>Double) extends PaintScale[T] { def apply(value : T) : Paint = { if (view(value).isNaN) { PaintScale.nanPaint } else { val index = gradient.length * (value - lower) / (upper - lower); gradient(math.min(gradient.length-1, math.max(0, index.toInt))); } } } /** * Maps items to colors using the given partial function. If no color * is provided for the given item, then returns PaintScale.nanPaint. * * @author dramage */ case class CategoricalPaintScale[T] (categories : PartialFunction[T,Paint]) extends PaintScale[T] { def apply(value : T) : Paint = { if (!categories.isDefinedAt(value)) { PaintScale.nanPaint } else { categories(value) } } } object PaintScale { /** * Convert a color description string into a color suitable for plotting. * @param colorcode A string that is a single character (like "k"), a name * (like "black"), "r,g,b" or, "[r,g,b]" * * @author Patryk Laurent */ def convertToColor(colorcode:String) : java.awt.Color = { val rgbcsv = "(.*),(.*),(.*)".r; colorcode.toLowerCase.replace(" ", "").replace("[","").replace("]", "") match { case "y" | "yellow" => yellow case "m" | "magenta" => magenta case "c" | "cyan" => cyan case "r" | "red" => red case "g" | "green" => green case "b" | "blue" => blue case "w" | "white" => white case "k" | "black" => black case rgbcsv(r,g,b) => new java.awt.Color(r.toInt,g.toInt,b.toInt) case uninterpretable:String => throw new IllegalArgumentException( "Expected color code to be either y m c r g b w k OR R,G,B or " + "[R,G,B] where R,G,B are numbers such that 0<=R,G,B<=255, but got '" + uninterpretable + "' instead.") } } /** Creates a GradientPaintScale automatically for the given range. */ implicit def gradientTuple[T](vLowerUpper : (T,T))(implicit view : T=>Double) : GradientPaintScale[T] = GradientPaintScale[T](vLowerUpper._1, vLowerUpper._2); /** Creates a CategoricalPaintScale from the provided partial function. */ implicit def literalColorMap[T](map : PartialFunction[T,Paint]) : CategoricalPaintScale[T] = CategoricalPaintScale[T](map); // // Default colors and patterns. // /** For painting NaN. */ val nanPaint = { val img = new BufferedImage(5,5,BufferedImage.TYPE_INT_ARGB); val gfx = img.getGraphics; gfx.setColor(Color.gray); gfx.drawLine(0,0,4,4); gfx.dispose(); new TexturePaint(img, new Rectangle2D.Double(0,0,5,5)); } /** The Category10 palette from Protovis http://vis.stanford.edu/protovis/docs/color.html */ object Category10 { val values : Array[Color] = Array( "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" ).map(Color.decode); val blue = values(0); val orange = values(1); val green = values(2); val red = values(3); val purple = values(4); val brown = values(5); val magenta = values(6); val gray = values(7); val gold = values(8); val teal = values(9); def apply(i : Int) = values(i); } /** The Category20 palette from Protovis http://vis.stanford.edu/protovis/docs/color.html */ object Category20 { val values : Array[Color] = Category10.values ++ Array( "#aec7e8", "#ffbb78", "#98df8a", "#ff9896", "#c5b0d5", "#c49c94", "#f7b6d2", "#c7c7c7", "#dbdb8d", "#9edae5" ).map(Color.decode); val lightblue = values(10); val lightorange = values(11); val lightgreen = values(12); val lightred = values(13); val lightpurple = values(14); val lightbrown = values(15); val lightmagenta = values(16); val lightgray = values(17); val lightgold = values(18); val lightteal = values(19); def apply(i : Int) = values(i); } // // A large pallete of color literals from ProtoVis // val aliceblue = Color.decode( "#f0f8ff"); val antiquewhite = Color.decode( "#faebd7"); val aqua = Color.decode( "#00ffff"); val aquamarine = Color.decode( "#7fffd4"); val azure = Color.decode( "#f0ffff"); val beige = Color.decode( "#f5f5dc"); val bisque = Color.decode( "#ffe4c4"); val black = Color.decode( "#000000"); val blanchedalmond = Color.decode( "#ffebcd"); val blue = Color.decode( "#0000ff"); val blueviolet = Color.decode( "#8a2be2"); val brown = Color.decode( "#a52a2a"); val burlywood = Color.decode( "#deb887"); val cadetblue = Color.decode( "#5f9ea0"); val chartreuse = Color.decode( "#7fff00"); val chocolate = Color.decode( "#d2691e"); val coral = Color.decode( "#ff7f50"); val cornflowerblue = Color.decode( "#6495ed"); val cornsilk = Color.decode( "#fff8dc"); val crimson = Color.decode( "#dc143c"); val cyan = Color.decode( "#00ffff"); val darkblue = Color.decode( "#00008b"); val darkcyan = Color.decode( "#008b8b"); val darkgoldenrod = Color.decode( "#b8860b"); val darkgray = Color.decode( "#a9a9a9"); val darkgreen = Color.decode( "#006400"); val darkgrey = Color.decode( "#a9a9a9"); val darkkhaki = Color.decode( "#bdb76b"); val darkmagenta = Color.decode( "#8b008b"); val darkolivegreen = Color.decode( "#556b2f"); val darkorange = Color.decode( "#ff8c00"); val darkorchid = Color.decode( "#9932cc"); val darkred = Color.decode( "#8b0000"); val darksalmon = Color.decode( "#e9967a"); val darkseagreen = Color.decode( "#8fbc8f"); val darkslateblue = Color.decode( "#483d8b"); val darkslategray = Color.decode( "#2f4f4f"); val darkslategrey = Color.decode( "#2f4f4f"); val darkturquoise = Color.decode( "#00ced1"); val darkviolet = Color.decode( "#9400d3"); val deeppink = Color.decode( "#ff1493"); val deepskyblue = Color.decode( "#00bfff"); val dimgray = Color.decode( "#696969"); val dimgrey = Color.decode( "#696969"); val dodgerblue = Color.decode( "#1e90ff"); val firebrick = Color.decode( "#b22222"); val floralwhite = Color.decode( "#fffaf0"); val forestgreen = Color.decode( "#228b22"); val fuchsia = Color.decode( "#ff00ff"); val gainsboro = Color.decode( "#dcdcdc"); val ghostwhite = Color.decode( "#f8f8ff"); val gold = Color.decode( "#ffd700"); val goldenrod = Color.decode( "#daa520"); val gray = Color.decode( "#808080"); val green = Color.decode( "#008000"); val greenyellow = Color.decode( "#adff2f"); val grey = Color.decode( "#808080"); val honeydew = Color.decode( "#f0fff0"); val hotpink = Color.decode( "#ff69b4"); val indianred = Color.decode( "#cd5c5c"); val indigo = Color.decode( "#4b0082"); val ivory = Color.decode( "#fffff0"); val khaki = Color.decode( "#f0e68c"); val lavender = Color.decode( "#e6e6fa"); val lavenderblush = Color.decode( "#fff0f5"); val lawngreen = Color.decode( "#7cfc00"); val lemonchiffon = Color.decode( "#fffacd"); val lightblue = Color.decode( "#add8e6"); val lightcoral = Color.decode( "#f08080"); val lightcyan = Color.decode( "#e0ffff"); val lightgoldenrodyellow = Color.decode( "#fafad2"); val lightgray = Color.decode( "#d3d3d3"); val lightgreen = Color.decode( "#90ee90"); val lightgrey = Color.decode( "#d3d3d3"); val lightpink = Color.decode( "#ffb6c1"); val lightsalmon = Color.decode( "#ffa07a"); val lightseagreen = Color.decode( "#20b2aa"); val lightskyblue = Color.decode( "#87cefa"); val lightslategray = Color.decode( "#778899"); val lightslategrey = Color.decode( "#778899"); val lightsteelblue = Color.decode( "#b0c4de"); val lightyellow = Color.decode( "#ffffe0"); val lime = Color.decode( "#00ff00"); val limegreen = Color.decode( "#32cd32"); val linen = Color.decode( "#faf0e6"); val magenta = Color.decode( "#ff00ff"); val maroon = Color.decode( "#800000"); val mediumaquamarine = Color.decode( "#66cdaa"); val mediumblue = Color.decode( "#0000cd"); val mediumorchid = Color.decode( "#ba55d3"); val mediumpurple = Color.decode( "#9370db"); val mediumseagreen = Color.decode( "#3cb371"); val mediumslateblue = Color.decode( "#7b68ee"); val mediumspringgreen = Color.decode( "#00fa9a"); val mediumturquoise = Color.decode( "#48d1cc"); val mediumvioletred = Color.decode( "#c71585"); val midnightblue = Color.decode( "#191970"); val mintcream = Color.decode( "#f5fffa"); val mistyrose = Color.decode( "#ffe4e1"); val moccasin = Color.decode( "#ffe4b5"); val navajowhite = Color.decode( "#ffdead"); val navy = Color.decode( "#000080"); val oldlace = Color.decode( "#fdf5e6"); val olive = Color.decode( "#808000"); val olivedrab = Color.decode( "#6b8e23"); val orange = Color.decode( "#ffa500"); val orangered = Color.decode( "#ff4500"); val orchid = Color.decode( "#da70d6"); val palegoldenrod = Color.decode( "#eee8aa"); val palegreen = Color.decode( "#98fb98"); val paleturquoise = Color.decode( "#afeeee"); val palevioletred = Color.decode( "#db7093"); val papayawhip = Color.decode( "#ffefd5"); val peachpuff = Color.decode( "#ffdab9"); val peru = Color.decode( "#cd853f"); val pink = Color.decode( "#ffc0cb"); val plum = Color.decode( "#dda0dd"); val powderblue = Color.decode( "#b0e0e6"); val purple = Color.decode( "#800080"); val red = Color.decode( "#ff0000"); val rosybrown = Color.decode( "#bc8f8f"); val royalblue = Color.decode( "#4169e1"); val saddlebrown = Color.decode( "#8b4513"); val salmon = Color.decode( "#fa8072"); val sandybrown = Color.decode( "#f4a460"); val seagreen = Color.decode( "#2e8b57"); val seashell = Color.decode( "#fff5ee"); val sienna = Color.decode( "#a0522d"); val silver = Color.decode( "#c0c0c0"); val skyblue = Color.decode( "#87ceeb"); val slateblue = Color.decode( "#6a5acd"); val slategray = Color.decode( "#708090"); val slategrey = Color.decode( "#708090"); val snow = Color.decode( "#fffafa"); val springgreen = Color.decode( "#00ff7f"); val steelblue = Color.decode( "#4682b4"); val tan = Color.decode( "#d2b48c"); val teal = Color.decode( "#008080"); val thistle = Color.decode( "#d8bfd8"); val tomato = Color.decode( "#ff6347"); val turquoise = Color.decode( "#40e0d0"); val violet = Color.decode( "#ee82ee"); val wheat = Color.decode( "#f5deb3"); val white = Color.decode( "#ffffff"); val whitesmoke = Color.decode( "#f5f5f5"); val yellow = Color.decode( "#ffff00"); val yellowgreen = Color.decode( "#9acd32"); val transparent = new Color(0,0,0,0); /** Produces a gradient using the University of Minnesota's school colors, from maroon (low) to gold (high) */ lazy val MaroonToGold = createGradient(new Color(0xA0, 0x00, 0x00), new Color(0xFF, 0xFF, 0x00), 256); /** Produces a gradient from blue (low) to red (high) */ lazy val BlueToRed= createGradient(Color.BLUE, Color.RED, 500); /** Produces a gradient from black (low) to white (high) */ lazy val BlackToWhite = createGradient(Color.BLACK, Color.WHITE, 500); /** Produces a gradient from white (low) to black (high) */ lazy val WhiteToBlack = createGradient(Color.WHITE, Color.BLACK, 500); /** Produces a gradient from red (low) to green (high) */ lazy val RedToGreen = createGradient(Color.RED, Color.GREEN, 500); /** Produces a gradient through green, yellow, orange, red */ lazy val GreenYelloOrangeRed = createMultiGradient( Array(Color.green, Color.yellow, Color.orange, Color.red), 500); /** Produces a gradient through the rainbow: violet, blue, green, yellow, orange, red */ lazy val Rainbow = createMultiGradient( Array(new Color(181, 32, 255), Color.blue, Color.green, Color.yellow, Color.orange, Color.red), 500); /** Produces a gradient for hot things (black, red, orange, yellow, white) */ lazy val Hot = createMultiGradient( Array(Color.black, new Color(87, 0, 0), Color.red, Color.orange, Color.yellow, Color.white), 500); /** Produces a different gradient for hot things (black, brown, orange, white) */ lazy val Heat = createMultiGradient( Array(Color.black, new Color(105, 0, 0), new Color(192, 23, 0), new Color(255, 150, 38), Color.white), 500); /** Produces a gradient through red, orange, yellow */ lazy val RedOrangeYellow = createMultiGradient( Array(Color.red, Color.orange, Color.yellow), 500); /** * Creates an array of Color objects for use as a gradient, using a linear * interpolation between the two specified colors. * * From http://www.mbeckler.org/heatMap/heatMap.html * * @param one Color used for the bottom of the gradient * @param two Color used for the top of the gradient * @param numSteps The number of steps in the gradient. 250 is a good number. */ def createGradient(one : Color, two : Color, numSteps : Int) : Array[Color] = { val r1 = one.getRed(); val g1 = one.getGreen(); val b1 = one.getBlue(); val r2 = two.getRed(); val g2 = two.getGreen(); val b2 = two.getBlue(); val gradient = new Array[Color](numSteps); var iNorm : Double = 0; for (i <- 0 until numSteps) { iNorm = i / numSteps.toDouble; //a normalized [0:1] variable val newR = (r1 + iNorm * (r2 - r1)).toInt; val newG = (g1 + iNorm * (g2 - g1)).toInt; val newB = (b1 + iNorm * (b2 - b1)).toInt; gradient(i) = new Color(newR, newG, newB); } return gradient; } /** * Creates an array of Color objects for use as a gradient, using an array * of Color objects. It uses a linear interpolation between each pair of * points. * * From http://www.mbeckler.org/heatMap/heatMap.html * * @param colors An array of Color objects used for the gradient. The * Color at index 0 will be the lowest color. * * @param numSteps The number of steps in the gradient. 250 is a good number. */ def createMultiGradient(colors : Array[Color], numSteps : Int) : Array[Color] = { //we assume a linear gradient, with equal spacing between colors //The final gradient will be made up of n 'sections', where n = colors.length - 1 val numSections = colors.length - 1; var gradientIndex = 0; //points to the next open spot in the final gradient val gradient = new Array[Color](numSteps) require(numSections > 0, "Array must have at least two colors"); for (section <- 0 until numSections) { //we divide the gradient into (n - 1) sections, and do a regular gradient for each val temp = createGradient(colors(section), colors(section+1), numSteps / numSections); for (i <- 0 until temp.length) { //copy the sub-gradient into the overall gradient gradient(gradientIndex) = temp(i); gradientIndex += 1 } } if (gradientIndex < numSteps) { //The rounding didn't work out in our favor, and there is at least // one unfilled slot in the gradient[] array. //We can just copy the final color there while (gradientIndex < numSteps) { gradient(gradientIndex) = colors(colors.length - 1); gradientIndex += 1 } } return gradient; } } ================================================ FILE: src/main/scala/scalala/library/plotting/PaintScaleFactory.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; package plotting; import java.awt.{Color,Paint,TexturePaint}; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; /** * Constructs a PaintScale for the given type T by examining a set of its * values. * * @author dramage */ trait PaintScaleFactory[T] extends (Traversable[T] => PaintScale[T]); /** * Creates a GradientPaintScale from the min and max of a set of data points. * bound are supplied. * * @author dramage */ case class GradientPaintScaleFactory[T] (gradient : Array[Color] = PaintScale.WhiteToBlack) (implicit view : T=>Double) extends PaintScaleFactory[T] { override def apply(items : Traversable[T]) : PaintScale[T] = { var min = items.head; var max = items.head; for (item <- items) { if (!view(item).isNaN) { if (item < min) min = item; if (item > max) max = item; } } GradientPaintScale(min, max, gradient); } } /** * Creates a categorical paint scale using the Category20 palette borrowed from * Protovis. http://vis.stanford.edu/protovis/docs/color.html * * Beware that category colors can be reused if the number of distinct items * is greater than 20. * * @author dramage */ case class CategoricalPaintScaleFactory[T]() extends PaintScaleFactory[T] { override def apply(items : Traversable[T]) : PaintScale[T] = { val distinct = items.toList.distinct; CategoricalPaintScale[T](Map() ++ (distinct zip Stream.continually(PaintScale.Category20.values.toList).flatten)); } } object PaintScaleFactory { /** * Ignores incoming data, instead returns the provided PaintScale when * queried as a PaintScaleFactory. */ implicit def singletonFactoryForPaintScale[S,T](paintScale : S) (implicit view : S=>PaintScale[T]) : PaintScaleFactory[T] = new PaintScaleFactory[T] { def apply(items : Traversable[T]) = view(paintScale); } } ================================================ FILE: src/main/scala/scalala/library/plotting/XYPlot.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; package plotting; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.DefaultDrawingSupplier; import org.jfree.chart.axis.{NumberAxis,TickUnits,NumberTickUnit}; /** A two dimensional XY plot */ class XYPlot(figure : Figure) { val xaxis : NumberAxis = new NumberAxis(null); val yaxis : NumberAxis = new NumberAxis(null); // Save the default tick units. private val xaxisDefaultTickUnits = xaxis.getStandardTickUnits(); private val yaxisDefaultTickUnits = yaxis.getStandardTickUnits(); def setXAxisIntegerTickUnits() = xaxis.setStandardTickUnits(XYPlot.integerTickUnits); def setYAxisIntegerTickUnits() = yaxis.setStandardTickUnits(XYPlot.integerTickUnits); def setXAxisDecimalTickUnits() = xaxis.setStandardTickUnits(xaxisDefaultTickUnits); def setYAxisDecimalTickUnits() = yaxis.setStandardTickUnits(yaxisDefaultTickUnits); // set integer tick units by default Array(xaxis,yaxis) foreach (axis => { axis.setAutoRangeIncludesZero(false); axis.setStandardTickUnits(XYPlot.integerTickUnits); }); /** The JFreeChart plot object. */ lazy val plot = { val rv = new org.jfree.chart.plot.XYPlot(); rv.setDomainAxis(xaxis) rv.setRangeAxis(yaxis) rv.setDrawingSupplier(new DefaultDrawingSupplier( XYPlot.paints, XYPlot.fillPaints, XYPlot.outlinePaints, XYPlot.strokes, XYPlot.outlineStrokes, XYPlot.shapes)); rv; } /** Adds to the current plot if true, else replaces */ var hold : Boolean = false /** The plot title */ def title_=(str : String) : Unit = chart.setTitle(str); def title : String = chart.getTitle.getText; /** If we show a legend */ private var _legend : Boolean = false; def legend_=(show : Boolean) : Unit = { chart.removeLegend(); if (show) { import org.jfree.chart.title._; import org.jfree.ui._; import org.jfree.chart.block._; import java.awt.Color; val legend = new LegendTitle(this.plot); legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0)); legend.setFrame(new LineBorder()); legend.setBackgroundPaint(Color.WHITE); legend.setPosition(RectangleEdge.BOTTOM); chart.addLegend(legend); } _legend = show refresh() } def legend : Boolean = _legend /** The current series */ private var _series : Int = -1 def series = _series /** Returns the next series number as per the current hold policy */ def nextSeries : Int = { if (hold) { _series += 1 } else { _series = 0 for (i <- 0 until plot.getDatasetCount()) { plot.setDataset(i,null); plot.setRenderer(i,null); } // remove all subtitles, particularly so we can kill all legends while (chart.getSubtitleCount > 0) { chart.removeSubtitle(chart.getSubtitle(0)); } // re-add the (now-empty) legend for consistency legend = _legend; // reset to integer ticks setXAxisIntegerTickUnits(); setYAxisIntegerTickUnits(); } return _series } /** The JFreeChart for this plot */ lazy val chart = { val rv = new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, plot, false); rv.setBackgroundPaint(XYPlot.transparent); rv.setPadding(new org.jfree.ui.RectangleInsets(5,0,0,0)); rv; } /** The ChartPanel for this plot */ lazy val panel = new org.jfree.chart.ChartPanel(chart); /** Shows the given chart */ def refresh() = figure.refresh() } object XYPlot { import java.awt.{Color,Paint}; import org.jfree.chart.ChartColor._; import org.jfree.chart.plot.DefaultDrawingSupplier; /** Units for integer ticks on axes. */ val integerTickUnits = { val units = new TickUnits(); val df = new java.text.DecimalFormat("0"); for (b <- List(1,2,5); e <- List(0,1,2,3,4,5,6,7,8)) { units.add(new NumberTickUnit(b * math.pow(10,e).toInt, df)); } units; } // color cycle ignoring bright colors val paints : Array[Paint] = PaintScale.Category20.values.asInstanceOf[Array[Paint]]; def paint(series : Int) = paints(series % paints.length); val shapes = DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE; def shape(series : Int) = shapes(series % shapes.length); val strokes = DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE; def stroke(series : Int) = strokes(series % strokes.length); val fillPaints = paints; // DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE; def fillPaint(series : Int) = fillPaints(series % fillPaints.length); val outlinePaints = paints; // DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE; def outlinePaint(series : Int) = outlinePaints(series % outlinePaints.length); val outlineStrokes = DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE; def outlineStroke(series : Int) = outlineStrokes(series % outlineStrokes.length); val transparent = new Color(255,255,255,0); // // shapes // val dot = new java.awt.geom.Ellipse2D.Double(-1,-1,2,2); val plus = { val shape = new java.awt.geom.GeneralPath(); shape.moveTo(-3,0); shape.lineTo(3,0); shape.moveTo(0,-3); shape.lineTo(0,3); shape; }; } ================================================ FILE: src/main/scala/scalala/operators/BinaryOp.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scala.annotation.implicitNotFound; import scala.collection.generic.CanBuildFrom; import scalala.scalar.Scalar; /** * Operation of type O that returns That from arguments A and B. * * @author dramage */ @implicitNotFound(msg="Could not find a way to ${O} values of type ${A} and ${B}") trait BinaryOp[@specialized -A, @specialized -B, O<:OpType, +To] extends ((A,B) => To) { def opType : O; } trait BinaryOpImplicitsLevel0 { /** * Recursively add together the values from two maps. Assumes all keys * are in both maps. */ implicit def OpRecurseMapMap[K,V1,V2,RV,O<:OpType,M,That] (implicit view : M=>scala.collection.Map[K,V1], op : BinaryOp[V1,V2,O,RV], c : CompatibleShape[V1,V2], bf : CanBuildFrom[M,(K,RV),That]) : BinaryOp[M, scala.collection.Map[K,V2], O, That] = new BinaryOp[M, scala.collection.Map[K,V2], O, That] { def opType = op.opType; def apply(a : M, b : scala.collection.Map[K,V2]) = { val builder = bf(a); for (k <- (a.keySet | b.keySet)) { builder += k -> op(a(k),b(k)); } builder.result; } } } object BinaryOp extends BinaryTupleOps with BinaryOpImplicitsLevel0 { // Int <-> Int implicit object OpAddII extends BinaryOp[Int,Int,OpAdd,Int] { def opType = OpAdd; def apply(a : Int, b : Int) = a + b; } implicit object OpSubII extends BinaryOp[Int,Int,OpSub,Int] { def opType = OpSub; def apply(a : Int, b : Int) = a - b; } implicit object OpMulII extends BinaryOp[Int,Int,OpMul,Int] { def opType = OpMul; def apply(a : Int, b : Int) = a * b; } implicit object OpDivII extends BinaryOp[Int,Int,OpDiv,Int] { def opType = OpDiv; def apply(a : Int, b : Int) = a / b; } implicit object OpModII extends BinaryOp[Int,Int,OpMod,Int] { def opType = OpMod; def apply(a : Int, b : Int) = a % b; } implicit object OpPowII extends BinaryOp[Int,Int,OpPow,Double] { def opType = OpPow; def apply(a : Int, b : Int) = math.pow(a,b); } implicit object OpLTII extends BinaryOp[Int,Int,OpLT,Boolean] { def opType = OpLT; def apply(a : Int, b : Int) = a < b; } implicit object OpLTEII extends BinaryOp[Int,Int,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Int, b : Int) = a <= b; } implicit object OpGTII extends BinaryOp[Int,Int,OpGT,Boolean] { def opType = OpGT; def apply(a : Int, b : Int) = a > b; } implicit object OpGTEII extends BinaryOp[Int,Int,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Int, b : Int) = a >= b; } implicit object OpEqII extends BinaryOp[Int,Int,OpEq,Boolean] { def opType = OpEq; def apply(a : Int, b : Int) = a == b; } implicit object OpNeII extends BinaryOp[Int,Int,OpNe,Boolean] { def opType = OpNe; def apply(a : Int, b : Int) = a != b; } implicit object OpAndII extends BinaryOp[Int,Int,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Int, b : Int) = a != 0 && b != 0; } implicit object OpOrII extends BinaryOp[Int,Int,OpOr,Boolean] { def opType = OpOr; def apply(a : Int, b : Int) = a != 0 || b != 0; } implicit object OpXorII extends BinaryOp[Int,Int,OpXor,Boolean] { def opType = OpXor; def apply(a : Int, b : Int) = (a != 0) ^ (b != 0); } // Long <-> Long implicit object OpAddLL extends BinaryOp[Long,Long,OpAdd,Long] { def opType = OpAdd; def apply(a : Long, b : Long) = a + b; } implicit object OpSubLL extends BinaryOp[Long,Long,OpSub,Long] { def opType = OpSub; def apply(a : Long, b : Long) = a - b; } implicit object OpMulLL extends BinaryOp[Long,Long,OpMul,Long] { def opType = OpMul; def apply(a : Long, b : Long) = a * b; } implicit object OpDivLL extends BinaryOp[Long,Long,OpDiv,Long] { def opType = OpDiv; def apply(a : Long, b : Long) = a / b; } implicit object OpModLL extends BinaryOp[Long,Long,OpMod,Long] { def opType = OpMod; def apply(a : Long, b : Long) = a % b; } implicit object OpPowLL extends BinaryOp[Long,Long,OpPow,Double] { def opType = OpPow; def apply(a : Long, b : Long) = math.pow(a,b); } implicit object OpLTLL extends BinaryOp[Long,Long,OpLT,Boolean] { def opType = OpLT; def apply(a : Long, b : Long) = a < b; } implicit object OpLTELL extends BinaryOp[Long,Long,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Long, b : Long) = a <= b; } implicit object OpGTLL extends BinaryOp[Long,Long,OpGT,Boolean] { def opType = OpGT; def apply(a : Long, b : Long) = a > b; } implicit object OpGTELL extends BinaryOp[Long,Long,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Long, b : Long) = a >= b; } implicit object OpEqLL extends BinaryOp[Long,Long,OpEq,Boolean] { def opType = OpEq; def apply(a : Long, b : Long) = a == b; } implicit object OpNeLL extends BinaryOp[Long,Long,OpNe,Boolean] { def opType = OpNe; def apply(a : Long, b : Long) = a != b; } implicit object OpAndLL extends BinaryOp[Long,Long,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Long, b : Long) = a != 0 && b != 0; } implicit object OpOrLL extends BinaryOp[Long,Long,OpOr,Boolean] { def opType = OpOr; def apply(a : Long, b : Long) = a != 0 || b != 0; } implicit object OpXorLL extends BinaryOp[Long,Long,OpXor,Boolean] { def opType = OpXor; def apply(a : Long, b : Long) = (a != 0) ^ (b != 0); } // Float <-> Float implicit object OpAddFF extends BinaryOp[Float,Float,OpAdd,Float] { def opType = OpAdd; def apply(a : Float, b : Float) = a + b; } implicit object OpSubFF extends BinaryOp[Float,Float,OpSub,Float] { def opType = OpSub; def apply(a : Float, b : Float) = a - b; } implicit object OpMulFF extends BinaryOp[Float,Float,OpMul,Float] { def opType = OpMul; def apply(a : Float, b : Float) = a * b; } implicit object OpDivFF extends BinaryOp[Float,Float,OpDiv,Float] { def opType = OpDiv; def apply(a : Float, b : Float) = a / b; } implicit object OpModFF extends BinaryOp[Float,Float,OpMod,Float] { def opType = OpMod; def apply(a : Float, b : Float) = a % b; } implicit object OpPowFF extends BinaryOp[Float,Float,OpPow,Double] { def opType = OpPow; def apply(a : Float, b : Float) = math.pow(a,b); } implicit object OpLTFF extends BinaryOp[Float,Float,OpLT,Boolean] { def opType = OpLT; def apply(a : Float, b : Float) = a < b; } implicit object OpLTEFF extends BinaryOp[Float,Float,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Float, b : Float) = a <= b; } implicit object OpGTFF extends BinaryOp[Float,Float,OpGT,Boolean] { def opType = OpGT; def apply(a : Float, b : Float) = a > b; } implicit object OpGTEFF extends BinaryOp[Float,Float,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Float, b : Float) = a >= b; } implicit object OpEqFF extends BinaryOp[Float,Float,OpEq,Boolean] { def opType = OpEq; def apply(a : Float, b : Float) = a == b; } implicit object OpNeFF extends BinaryOp[Float,Float,OpNe,Boolean] { def opType = OpNe; def apply(a : Float, b : Float) = a != b; } implicit object OpAndFF extends BinaryOp[Float,Float,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Float, b : Float) = a != 0 && b != 0; } implicit object OpOrFF extends BinaryOp[Float,Float,OpOr,Boolean] { def opType = OpOr; def apply(a : Float, b : Float) = a != 0 || b != 0; } implicit object OpXorFF extends BinaryOp[Float,Float,OpXor,Boolean] { def opType = OpXor; def apply(a : Float, b : Float) = (a != 0) ^ (b != 0); } // Double <-> Double implicit object OpAddDD extends BinaryOp[Double,Double,OpAdd,Double] { def opType = OpAdd; def apply(a : Double, b : Double) = a + b; } implicit object OpSubDD extends BinaryOp[Double,Double,OpSub,Double] { def opType = OpSub; def apply(a : Double, b : Double) = a - b; } implicit object OpMulDD extends BinaryOp[Double,Double,OpMul,Double] { def opType = OpMul; def apply(a : Double, b : Double) = a * b; } implicit object OpDivDD extends BinaryOp[Double,Double,OpDiv,Double] { def opType = OpDiv; def apply(a : Double, b : Double) = a / b; } implicit object OpModDD extends BinaryOp[Double,Double,OpMod,Double] { def opType = OpMod; def apply(a : Double, b : Double) = a % b; } implicit object OpPowDD extends BinaryOp[Double,Double,OpPow,Double] { def opType = OpPow; def apply(a : Double, b : Double) = math.pow(a,b); } implicit object OpLTDD extends BinaryOp[Double,Double,OpLT,Boolean] { def opType = OpLT; def apply(a : Double, b : Double) = a < b; } implicit object OpLTEDD extends BinaryOp[Double,Double,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Double, b : Double) = a <= b; } implicit object OpGTDD extends BinaryOp[Double,Double,OpGT,Boolean] { def opType = OpGT; def apply(a : Double, b : Double) = a > b; } implicit object OpGTEDD extends BinaryOp[Double,Double,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Double, b : Double) = a >= b; } implicit object OpEqDD extends BinaryOp[Double,Double,OpEq,Boolean] { def opType = OpEq; def apply(a : Double, b : Double) = a == b; } implicit object OpNeDD extends BinaryOp[Double,Double,OpNe,Boolean] { def opType = OpNe; def apply(a : Double, b : Double) = a != b; } implicit object OpAndDD extends BinaryOp[Double,Double,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Double, b : Double) = a != 0 && b != 0; } implicit object OpOrDD extends BinaryOp[Double,Double,OpOr,Boolean] { def opType = OpOr; def apply(a : Double, b : Double) = a != 0 || b != 0; } implicit object OpXorDD extends BinaryOp[Double,Double,OpXor,Boolean] { def opType = OpXor; def apply(a : Double, b : Double) = (a != 0) ^ (b != 0); } // Int <-> Double implicit object OpAddID extends BinaryOp[Int,Double,OpAdd,Double] { def opType = OpAdd; def apply(a : Int, b : Double) = a + b; } implicit object OpSubID extends BinaryOp[Int,Double,OpSub,Double] { def opType = OpSub; def apply(a : Int, b : Double) = a - b; } implicit object OpMulID extends BinaryOp[Int,Double,OpMul,Double] { def opType = OpMul; def apply(a : Int, b : Double) = a * b; } implicit object OpDivID extends BinaryOp[Int,Double,OpDiv,Double] { def opType = OpDiv; def apply(a : Int, b : Double) = a / b; } implicit object OpModID extends BinaryOp[Int,Double,OpMod,Double] { def opType = OpMod; def apply(a : Int, b : Double) = a % b; } implicit object OpPowID extends BinaryOp[Int,Double,OpPow,Double] { def opType = OpPow; def apply(a : Int, b : Double) = math.pow(a,b); } implicit object OpLTID extends BinaryOp[Int,Double,OpLT,Boolean] { def opType = OpLT; def apply(a : Int, b : Double) = a < b; } implicit object OpLTEID extends BinaryOp[Int,Double,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Int, b : Double) = a <= b; } implicit object OpGTID extends BinaryOp[Int,Double,OpGT,Boolean] { def opType = OpGT; def apply(a : Int, b : Double) = a > b; } implicit object OpGTEID extends BinaryOp[Int,Double,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Int, b : Double) = a >= b; } implicit object OpEqID extends BinaryOp[Int,Double,OpEq,Boolean] { def opType = OpEq; def apply(a : Int, b : Double) = a == b; } implicit object OpNeID extends BinaryOp[Int,Double,OpNe,Boolean] { def opType = OpNe; def apply(a : Int, b : Double) = a != b; } implicit object OpAndID extends BinaryOp[Int,Double,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Int, b : Double) = a != 0 && b != 0; } implicit object OpOrID extends BinaryOp[Int,Double,OpOr,Boolean] { def opType = OpOr; def apply(a : Int, b : Double) = a != 0 || b != 0; } implicit object OpXorID extends BinaryOp[Int,Double,OpXor,Boolean] { def opType = OpXor; def apply(a : Int, b : Double) = (a != 0) ^ (b != 0); } // Double <-> Int implicit object OpAddDI extends BinaryOp[Double,Int,OpAdd,Double] { def opType = OpAdd; def apply(a : Double, b : Int) = a + b; } implicit object OpSubDI extends BinaryOp[Double,Int,OpSub,Double] { def opType = OpSub; def apply(a : Double, b : Int) = a - b; } implicit object OpMulDI extends BinaryOp[Double,Int,OpMul,Double] { def opType = OpMul; def apply(a : Double, b : Int) = a * b; } implicit object OpDivDI extends BinaryOp[Double,Int,OpDiv,Double] { def opType = OpDiv; def apply(a : Double, b : Int) = a / b; } implicit object OpModDI extends BinaryOp[Double,Int,OpMod,Double] { def opType = OpMod; def apply(a : Double, b : Int) = a % b; } implicit object OpPowDI extends BinaryOp[Double,Int,OpPow,Double] { def opType = OpPow; def apply(a : Double, b : Int) = math.pow(a,b); } implicit object OpLTDI extends BinaryOp[Double,Int,OpLT,Boolean] { def opType = OpLT; def apply(a : Double, b : Int) = a < b; } implicit object OpLTEDI extends BinaryOp[Double,Int,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Double, b : Int) = a <= b; } implicit object OpGTDI extends BinaryOp[Double,Int,OpGT,Boolean] { def opType = OpGT; def apply(a : Double, b : Int) = a > b; } implicit object OpGTEDI extends BinaryOp[Double,Int,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Double, b : Int) = a >= b; } implicit object OpEqDI extends BinaryOp[Double,Int,OpEq,Boolean] { def opType = OpEq; def apply(a : Double, b : Int) = a == b; } implicit object OpNeDI extends BinaryOp[Double,Int,OpNe,Boolean] { def opType = OpNe; def apply(a : Double, b : Int) = a != b; } implicit object OpAndDI extends BinaryOp[Double,Int,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Double, b : Int) = a != 0 && b != 0; } implicit object OpOrDI extends BinaryOp[Double,Int,OpOr,Boolean] { def opType = OpOr; def apply(a : Double, b : Int) = a != 0 || b != 0; } implicit object OpXorDI extends BinaryOp[Double,Int,OpXor,Boolean] { def opType = OpXor; def apply(a : Double, b : Int) = (a != 0) ^ (b != 0); } // Int <-> Float implicit object OpAddIF extends BinaryOp[Int,Float,OpAdd,Float] { def opType = OpAdd; def apply(a : Int, b : Float) = a + b; } implicit object OpSubIF extends BinaryOp[Int,Float,OpSub,Float] { def opType = OpSub; def apply(a : Int, b : Float) = a - b; } implicit object OpMulIF extends BinaryOp[Int,Float,OpMul,Float] { def opType = OpMul; def apply(a : Int, b : Float) = a * b; } implicit object OpDivIF extends BinaryOp[Int,Float,OpDiv,Float] { def opType = OpDiv; def apply(a : Int, b : Float) = a / b; } implicit object OpModIF extends BinaryOp[Int,Float,OpMod,Float] { def opType = OpMod; def apply(a : Int, b : Float) = a % b; } implicit object OpPowIF extends BinaryOp[Int,Float,OpPow,Double] { def opType = OpPow; def apply(a : Int, b : Float) = math.pow(a,b); } implicit object OpLTIF extends BinaryOp[Int,Float,OpLT,Boolean] { def opType = OpLT; def apply(a : Int, b : Float) = a < b; } implicit object OpLTEIF extends BinaryOp[Int,Float,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Int, b : Float) = a <= b; } implicit object OpGTIF extends BinaryOp[Int,Float,OpGT,Boolean] { def opType = OpGT; def apply(a : Int, b : Float) = a > b; } implicit object OpGTEIF extends BinaryOp[Int,Float,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Int, b : Float) = a >= b; } implicit object OpEqIF extends BinaryOp[Int,Float,OpEq,Boolean] { def opType = OpEq; def apply(a : Int, b : Float) = a == b; } implicit object OpNeIF extends BinaryOp[Int,Float,OpNe,Boolean] { def opType = OpNe; def apply(a : Int, b : Float) = a != b; } implicit object OpAndIF extends BinaryOp[Int,Float,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Int, b : Float) = a != 0 && b != 0; } implicit object OpOrIF extends BinaryOp[Int,Float,OpOr,Boolean] { def opType = OpOr; def apply(a : Int, b : Float) = a != 0 || b != 0; } implicit object OpXorIF extends BinaryOp[Int,Float,OpXor,Boolean] { def opType = OpXor; def apply(a : Int, b : Float) = (a != 0) ^ (b != 0); } // Float <-> Int implicit object OpAddFI extends BinaryOp[Float,Int,OpAdd,Float] { def opType = OpAdd; def apply(a : Float, b : Int) = a + b; } implicit object OpSubFI extends BinaryOp[Float,Int,OpSub,Float] { def opType = OpSub; def apply(a : Float, b : Int) = a - b; } implicit object OpMulFI extends BinaryOp[Float,Int,OpMul,Float] { def opType = OpMul; def apply(a : Float, b : Int) = a * b; } implicit object OpDivFI extends BinaryOp[Float,Int,OpDiv,Float] { def opType = OpDiv; def apply(a : Float, b : Int) = a / b; } implicit object OpModFI extends BinaryOp[Float,Int,OpMod,Float] { def opType = OpMod; def apply(a : Float, b : Int) = a % b; } implicit object OpPowFI extends BinaryOp[Float,Int,OpPow,Double] { def opType = OpPow; def apply(a : Float, b : Int) = math.pow(a,b); } implicit object OpLTFI extends BinaryOp[Float,Int,OpLT,Boolean] { def opType = OpLT; def apply(a : Float, b : Int) = a < b; } implicit object OpLTEFI extends BinaryOp[Float,Int,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Float, b : Int) = a <= b; } implicit object OpGTFI extends BinaryOp[Float,Int,OpGT,Boolean] { def opType = OpGT; def apply(a : Float, b : Int) = a > b; } implicit object OpGTEFI extends BinaryOp[Float,Int,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Float, b : Int) = a >= b; } implicit object OpEqFI extends BinaryOp[Float,Int,OpEq,Boolean] { def opType = OpEq; def apply(a : Float, b : Int) = a == b; } implicit object OpNeFI extends BinaryOp[Float,Int,OpNe,Boolean] { def opType = OpNe; def apply(a : Float, b : Int) = a != b; } implicit object OpAndFI extends BinaryOp[Float,Int,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Float, b : Int) = a != 0 && b != 0; } implicit object OpOrFI extends BinaryOp[Float,Int,OpOr,Boolean] { def opType = OpOr; def apply(a : Float, b : Int) = a != 0 || b != 0; } implicit object OpXorFI extends BinaryOp[Float,Int,OpXor,Boolean] { def opType = OpXor; def apply(a : Float, b : Int) = (a != 0) ^ (b != 0); } // Int <-> Long implicit object OpAddIL extends BinaryOp[Int,Long,OpAdd,Long] { def opType = OpAdd; def apply(a : Int, b : Long) = a + b; } implicit object OpSubIL extends BinaryOp[Int,Long,OpSub,Long] { def opType = OpSub; def apply(a : Int, b : Long) = a - b; } implicit object OpMulIL extends BinaryOp[Int,Long,OpMul,Long] { def opType = OpMul; def apply(a : Int, b : Long) = a * b; } implicit object OpDivIL extends BinaryOp[Int,Long,OpDiv,Long] { def opType = OpDiv; def apply(a : Int, b : Long) = a / b; } implicit object OpModIL extends BinaryOp[Int,Long,OpMod,Long] { def opType = OpMod; def apply(a : Int, b : Long) = a % b; } implicit object OpPowIL extends BinaryOp[Int,Long,OpPow,Double] { def opType = OpPow; def apply(a : Int, b : Long) = math.pow(a,b); } implicit object OpLTIL extends BinaryOp[Int,Long,OpLT,Boolean] { def opType = OpLT; def apply(a : Int, b : Long) = a < b; } implicit object OpLTEIL extends BinaryOp[Int,Long,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Int, b : Long) = a <= b; } implicit object OpGTIL extends BinaryOp[Int,Long,OpGT,Boolean] { def opType = OpGT; def apply(a : Int, b : Long) = a > b; } implicit object OpGTEIL extends BinaryOp[Int,Long,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Int, b : Long) = a >= b; } implicit object OpEqIL extends BinaryOp[Int,Long,OpEq,Boolean] { def opType = OpEq; def apply(a : Int, b : Long) = a == b; } implicit object OpNeIL extends BinaryOp[Int,Long,OpNe,Boolean] { def opType = OpNe; def apply(a : Int, b : Long) = a != b; } implicit object OpAndIL extends BinaryOp[Int,Long,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Int, b : Long) = a != 0 && b != 0; } implicit object OpOrIL extends BinaryOp[Int,Long,OpOr,Boolean] { def opType = OpOr; def apply(a : Int, b : Long) = a != 0 || b != 0; } implicit object OpXorIL extends BinaryOp[Int,Long,OpXor,Boolean] { def opType = OpXor; def apply(a : Int, b : Long) = (a != 0) ^ (b != 0); } // Long <-> Int implicit object OpAddLI extends BinaryOp[Long,Int,OpAdd,Long] { def opType = OpAdd; def apply(a : Long, b : Int) = a + b; } implicit object OpSubLI extends BinaryOp[Long,Int,OpSub,Long] { def opType = OpSub; def apply(a : Long, b : Int) = a - b; } implicit object OpMulLI extends BinaryOp[Long,Int,OpMul,Long] { def opType = OpMul; def apply(a : Long, b : Int) = a * b; } implicit object OpDivLI extends BinaryOp[Long,Int,OpDiv,Long] { def opType = OpDiv; def apply(a : Long, b : Int) = a / b; } implicit object OpModLI extends BinaryOp[Long,Int,OpMod,Long] { def opType = OpMod; def apply(a : Long, b : Int) = a % b; } implicit object OpPowLI extends BinaryOp[Long,Int,OpPow,Double] { def opType = OpPow; def apply(a : Long, b : Int) = math.pow(a,b); } implicit object OpLTLI extends BinaryOp[Long,Int,OpLT,Boolean] { def opType = OpLT; def apply(a : Long, b : Int) = a < b; } implicit object OpLTELI extends BinaryOp[Long,Int,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Long, b : Int) = a <= b; } implicit object OpGTLI extends BinaryOp[Long,Int,OpGT,Boolean] { def opType = OpGT; def apply(a : Long, b : Int) = a > b; } implicit object OpGTELI extends BinaryOp[Long,Int,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Long, b : Int) = a >= b; } implicit object OpEqLI extends BinaryOp[Long,Int,OpEq,Boolean] { def opType = OpEq; def apply(a : Long, b : Int) = a == b; } implicit object OpNeLI extends BinaryOp[Long,Int,OpNe,Boolean] { def opType = OpNe; def apply(a : Long, b : Int) = a != b; } implicit object OpAndLI extends BinaryOp[Long,Int,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Long, b : Int) = a != 0 && b != 0; } implicit object OpOrLI extends BinaryOp[Long,Int,OpOr,Boolean] { def opType = OpOr; def apply(a : Long, b : Int) = a != 0 || b != 0; } implicit object OpXorLI extends BinaryOp[Long,Int,OpXor,Boolean] { def opType = OpXor; def apply(a : Long, b : Int) = (a != 0) ^ (b != 0); } // Float <-> Double implicit object OpAddFD extends BinaryOp[Float,Double,OpAdd,Double] { def opType = OpAdd; def apply(a : Float, b : Double) = a + b; } implicit object OpSubFD extends BinaryOp[Float,Double,OpSub,Double] { def opType = OpSub; def apply(a : Float, b : Double) = a - b; } implicit object OpMulFD extends BinaryOp[Float,Double,OpMul,Double] { def opType = OpMul; def apply(a : Float, b : Double) = a * b; } implicit object OpDivFD extends BinaryOp[Float,Double,OpDiv,Double] { def opType = OpDiv; def apply(a : Float, b : Double) = a / b; } implicit object OpModFD extends BinaryOp[Float,Double,OpMod,Double] { def opType = OpMod; def apply(a : Float, b : Double) = a % b; } implicit object OpPowFD extends BinaryOp[Float,Double,OpPow,Double] { def opType = OpPow; def apply(a : Float, b : Double) = math.pow(a,b); } implicit object OpLTFD extends BinaryOp[Float,Double,OpLT,Boolean] { def opType = OpLT; def apply(a : Float, b : Double) = a < b; } implicit object OpLTEFD extends BinaryOp[Float,Double,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Float, b : Double) = a <= b; } implicit object OpGTFD extends BinaryOp[Float,Double,OpGT,Boolean] { def opType = OpGT; def apply(a : Float, b : Double) = a > b; } implicit object OpGTEFD extends BinaryOp[Float,Double,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Float, b : Double) = a >= b; } implicit object OpEqFD extends BinaryOp[Float,Double,OpEq,Boolean] { def opType = OpEq; def apply(a : Float, b : Double) = a == b; } implicit object OpNeFD extends BinaryOp[Float,Double,OpNe,Boolean] { def opType = OpNe; def apply(a : Float, b : Double) = a != b; } implicit object OpAndFD extends BinaryOp[Float,Double,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Float, b : Double) = a != 0 && b != 0; } implicit object OpOrFD extends BinaryOp[Float,Double,OpOr,Boolean] { def opType = OpOr; def apply(a : Float, b : Double) = a != 0 || b != 0; } implicit object OpXorFD extends BinaryOp[Float,Double,OpXor,Boolean] { def opType = OpXor; def apply(a : Float, b : Double) = (a != 0) ^ (b != 0); } // Double <-> Float implicit object OpAddDF extends BinaryOp[Double,Float,OpAdd,Double] { def opType = OpAdd; def apply(a : Double, b : Float) = a + b; } implicit object OpSubDF extends BinaryOp[Double,Float,OpSub,Double] { def opType = OpSub; def apply(a : Double, b : Float) = a - b; } implicit object OpMulDF extends BinaryOp[Double,Float,OpMul,Double] { def opType = OpMul; def apply(a : Double, b : Float) = a * b; } implicit object OpDivDF extends BinaryOp[Double,Float,OpDiv,Double] { def opType = OpDiv; def apply(a : Double, b : Float) = a / b; } implicit object OpModDF extends BinaryOp[Double,Float,OpMod,Double] { def opType = OpMod; def apply(a : Double, b : Float) = a % b; } implicit object OpPowDF extends BinaryOp[Double,Float,OpPow,Double] { def opType = OpPow; def apply(a : Double, b : Float) = math.pow(a,b); } implicit object OpLTDF extends BinaryOp[Double,Float,OpLT,Boolean] { def opType = OpLT; def apply(a : Double, b : Float) = a < b; } implicit object OpLTEDF extends BinaryOp[Double,Float,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Double, b : Float) = a <= b; } implicit object OpGTDF extends BinaryOp[Double,Float,OpGT,Boolean] { def opType = OpGT; def apply(a : Double, b : Float) = a > b; } implicit object OpGTEDF extends BinaryOp[Double,Float,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Double, b : Float) = a >= b; } implicit object OpEqDF extends BinaryOp[Double,Float,OpEq,Boolean] { def opType = OpEq; def apply(a : Double, b : Float) = a == b; } implicit object OpNeDF extends BinaryOp[Double,Float,OpNe,Boolean] { def opType = OpNe; def apply(a : Double, b : Float) = a != b; } implicit object OpAndDF extends BinaryOp[Double,Float,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Double, b : Float) = a != 0 && b != 0; } implicit object OpOrDF extends BinaryOp[Double,Float,OpOr,Boolean] { def opType = OpOr; def apply(a : Double, b : Float) = a != 0 || b != 0; } implicit object OpXorDF extends BinaryOp[Double,Float,OpXor,Boolean] { def opType = OpXor; def apply(a : Double, b : Float) = (a != 0) ^ (b != 0); } // Long <-> Double implicit object OpAddLD extends BinaryOp[Long,Double,OpAdd,Double] { def opType = OpAdd; def apply(a : Long, b : Double) = a + b; } implicit object OpSubLD extends BinaryOp[Long,Double,OpSub,Double] { def opType = OpSub; def apply(a : Long, b : Double) = a - b; } implicit object OpMulLD extends BinaryOp[Long,Double,OpMul,Double] { def opType = OpMul; def apply(a : Long, b : Double) = a * b; } implicit object OpDivLD extends BinaryOp[Long,Double,OpDiv,Double] { def opType = OpDiv; def apply(a : Long, b : Double) = a / b; } implicit object OpModLD extends BinaryOp[Long,Double,OpMod,Double] { def opType = OpMod; def apply(a : Long, b : Double) = a % b; } implicit object OpPowLD extends BinaryOp[Long,Double,OpPow,Double] { def opType = OpPow; def apply(a : Long, b : Double) = math.pow(a,b); } implicit object OpLTLD extends BinaryOp[Long,Double,OpLT,Boolean] { def opType = OpLT; def apply(a : Long, b : Double) = a < b; } implicit object OpLTELD extends BinaryOp[Long,Double,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Long, b : Double) = a <= b; } implicit object OpGTLD extends BinaryOp[Long,Double,OpGT,Boolean] { def opType = OpGT; def apply(a : Long, b : Double) = a > b; } implicit object OpGTELD extends BinaryOp[Long,Double,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Long, b : Double) = a >= b; } implicit object OpEqLD extends BinaryOp[Long,Double,OpEq,Boolean] { def opType = OpEq; def apply(a : Long, b : Double) = a == b; } implicit object OpNeLD extends BinaryOp[Long,Double,OpNe,Boolean] { def opType = OpNe; def apply(a : Long, b : Double) = a != b; } implicit object OpAndLD extends BinaryOp[Long,Double,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Long, b : Double) = a != 0 && b != 0; } implicit object OpOrLD extends BinaryOp[Long,Double,OpOr,Boolean] { def opType = OpOr; def apply(a : Long, b : Double) = a != 0 || b != 0; } implicit object OpXorLD extends BinaryOp[Long,Double,OpXor,Boolean] { def opType = OpXor; def apply(a : Long, b : Double) = (a != 0) ^ (b != 0); } // Double <-> Long implicit object OpAddDL extends BinaryOp[Double,Long,OpAdd,Double] { def opType = OpAdd; def apply(a : Double, b : Long) = a + b; } implicit object OpSubDL extends BinaryOp[Double,Long,OpSub,Double] { def opType = OpSub; def apply(a : Double, b : Long) = a - b; } implicit object OpMulDL extends BinaryOp[Double,Long,OpMul,Double] { def opType = OpMul; def apply(a : Double, b : Long) = a * b; } implicit object OpDivDL extends BinaryOp[Double,Long,OpDiv,Double] { def opType = OpDiv; def apply(a : Double, b : Long) = a / b; } implicit object OpModDL extends BinaryOp[Double,Long,OpMod,Double] { def opType = OpMod; def apply(a : Double, b : Long) = a % b; } implicit object OpPowDL extends BinaryOp[Double,Long,OpPow,Double] { def opType = OpPow; def apply(a : Double, b : Long) = math.pow(a,b); } implicit object OpLTDL extends BinaryOp[Double,Long,OpLT,Boolean] { def opType = OpLT; def apply(a : Double, b : Long) = a < b; } implicit object OpLTEDL extends BinaryOp[Double,Long,OpLTE,Boolean] { def opType = OpLTE; def apply(a : Double, b : Long) = a <= b; } implicit object OpGTDL extends BinaryOp[Double,Long,OpGT,Boolean] { def opType = OpGT; def apply(a : Double, b : Long) = a > b; } implicit object OpGTEDL extends BinaryOp[Double,Long,OpGTE,Boolean] { def opType = OpGTE; def apply(a : Double, b : Long) = a >= b; } implicit object OpEqDL extends BinaryOp[Double,Long,OpEq,Boolean] { def opType = OpEq; def apply(a : Double, b : Long) = a == b; } implicit object OpNeDL extends BinaryOp[Double,Long,OpNe,Boolean] { def opType = OpNe; def apply(a : Double, b : Long) = a != b; } implicit object OpAndDL extends BinaryOp[Double,Long,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Double, b : Long) = a != 0 && b != 0; } implicit object OpOrDL extends BinaryOp[Double,Long,OpOr,Boolean] { def opType = OpOr; def apply(a : Double, b : Long) = a != 0 || b != 0; } implicit object OpXorDL extends BinaryOp[Double,Long,OpXor,Boolean] { def opType = OpXor; def apply(a : Double, b : Long) = (a != 0) ^ (b != 0); } // Boolean <-> Boolean implicit object OpEqBB extends BinaryOp[Boolean,Boolean,OpEq,Boolean] { def opType = OpEq; def apply(a : Boolean, b : Boolean) = a == b; } implicit object OpNeBB extends BinaryOp[Boolean,Boolean,OpNe,Boolean] { def opType = OpNe; def apply(a : Boolean, b : Boolean) = a != b; } implicit object OpAndBB extends BinaryOp[Boolean,Boolean,OpAnd,Boolean] { def opType = OpAnd; def apply(a : Boolean, b : Boolean) = a && b; } implicit object OpOrBB extends BinaryOp[Boolean,Boolean,OpOr,Boolean] { def opType = OpOr; def apply(a : Boolean, b : Boolean) = a || b; } implicit object OpXorBB extends BinaryOp[Boolean,Boolean,OpXor,Boolean] { def opType = OpXor; def apply(a : Boolean, b : Boolean) = a ^ b; } // Boolean * Anything and vice versa implicit object OpMulBB extends BinaryOp[Boolean,Boolean,OpMul,Boolean] { def opType = OpMul; def apply(a : Boolean, b : Boolean) = a && b; } implicit object OpMulBI extends BinaryOp[Boolean,Int,OpMul,Int] { def opType = OpMul; def apply(a : Boolean, b : Int) = if (a) b else 0; } implicit object OpMulBL extends BinaryOp[Boolean,Long,OpMul,Long] { def opType = OpMul; def apply(a : Boolean, b : Long) = if (a) b else 0; } implicit object OpMulBF extends BinaryOp[Boolean,Float,OpMul,Float] { def opType = OpMul; def apply(a : Boolean, b : Float) = if (a) b else 0; } implicit object OpMulBD extends BinaryOp[Boolean,Double,OpMul,Double] { def opType = OpMul; def apply(a : Boolean, b : Double) = if (a) b else 0; } implicit object OpMulIB extends BinaryOp[Int,Boolean,OpMul,Int] { def opType = OpMul; def apply(a : Int, b : Boolean) = if (b) a else 0; } implicit object OpMulLB extends BinaryOp[Long,Boolean,OpMul,Long] { def opType = OpMul; def apply(a : Long, b : Boolean) = if (b) a else 0; } implicit object OpMulFB extends BinaryOp[Float,Boolean,OpMul,Float] { def opType = OpMul; def apply(a : Float, b : Boolean) = if (b) a else 0; } implicit object OpMulDB extends BinaryOp[Double,Boolean,OpMul,Double] { def opType = OpMul; def apply(a : Double, b : Boolean) = if (b) a else 0; } implicit def OpMulBooleanAny[V](implicit s : Scalar[V]) : BinaryOp[Boolean,V,OpMul,V] = new BinaryOp[Boolean,V,OpMul,V] { def opType = OpMul; def apply(a : Boolean, b : V) = if (a) b else s.zero; } implicit def OpMulAnyBoolean[V](implicit s : Scalar[V]) : BinaryOp[V,Boolean,OpMul,V] = new BinaryOp[V,Boolean,OpMul,V] { def opType = OpMul; def apply(a : V, b : Boolean) = if (b) a else s.zero; } // Double <-> Boolean implicit object OpAddDB extends BinaryOp[Double,Boolean,OpAdd,Double] { def opType = OpAdd; def apply(a : Double, b : Boolean) = if(b) a + 1 else a; } implicit object OpSubDB extends BinaryOp[Double,Boolean,OpSub,Double] { def opType = OpSub; def apply(a : Double, b : Boolean) = if(b) a - 1 else a; } implicit object OpPowDB extends BinaryOp[Double,Boolean,OpPow,Double] { def opType = OpPow; def apply(a : Double, b : Boolean) = math.pow(a,if(b) 1.0 else 0.0); } // // Promote regular scalar multiplications to shaped multiplications // implicit def promoteScalarMulToMulRowVectorBy[A,B,RV] (implicit view : A=>scalala.tensor.Tensor1Row[_,_], op : BinaryOp[A,B,OpMul,RV], s : Scalar[B]) : BinaryOp[A,B,OpMulRowVectorBy,RV] = new BinaryOp[A,B,OpMulRowVectorBy,RV] { def opType = OpMulRowVectorBy; def apply(a : A, b : B) = op(a,b); } implicit def promoteScalarMulToMulColVectorBy[A,B,RV] (implicit view : A=>scalala.tensor.Tensor1Col[_,_], op : BinaryOp[A,B,OpMul,RV], s : Scalar[B]) : BinaryOp[A,B,OpMulColVectorBy,RV] = new BinaryOp[A,B,OpMulColVectorBy,RV] { def opType = OpMulColVectorBy; def apply(a : A, b : B) = op(a,b); } implicit def promoteScalarMulToMulMatrixBy[A,B,RV] (implicit view : A=>scalala.tensor.Tensor2[_,_,_], op : BinaryOp[A,B,OpMul,RV], s : Scalar[B]) : BinaryOp[A,B,OpMulMatrixBy,RV] = new BinaryOp[A,B,OpMulMatrixBy,RV] { def opType = OpMulMatrixBy; def apply(a : A, b : B) = op(a,b); } // // Maps // implicit def OpLeafMapMap[K,V1,V2,RV,O<:OpType,M,That] (implicit view : M=>scala.collection.Map[K,V1], op : BinaryOp[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], bf : CanBuildFrom[M,(K,RV),That]) : BinaryOp[M, scala.collection.Map[K,V2], O, That] = new BinaryOp[M, scala.collection.Map[K,V2], O, That] { def opType = op.opType; def apply(a : M, b : scala.collection.Map[K,V2]) = { val builder = bf(a); for (k <- a.keySet) { builder += k -> op(a(k), b.getOrElse(k, s2.zero)); } for (k <- b.keySet) { if (!a.contains(k)) { builder += k -> op(s1.zero, b(k)); } } builder.result; } } implicit def OpMapScalar[K,V1,V2,RV,O<:OpType,M,That] (implicit view : M=>scala.collection.Map[K,V1], op : BinaryOp[V1,V2,O,RV], s : Scalar[V2], bf : CanBuildFrom[M,(K,RV),That]) : BinaryOp[M, V2, O, That] = new BinaryOp[M, V2, O, That] { def opType = op.opType; def apply(a : M, b : V2) = { val builder = bf(a); for ((k,v) <- a) { builder += k -> op(v,b); } builder.result; } } implicit def OpScalarMap[K,V1,V2,RV,O<:OpType,M,That] (implicit view : M=>scala.collection.Map[K,V2], op : BinaryOp[V1,V2,O,RV], s : Scalar[V1], bf : CanBuildFrom[M,(K,RV),That]) : BinaryOp[V1, M, O, That] = new BinaryOp[V1, M, O, That] { def opType = op.opType; def apply(a : V1, b : M) = { val builder = bf(b); for ((k,v) <- b) { builder += k -> op(a,v); } builder.result; } } // // Seqs // implicit def OpSeqSeq[V1,V2,RV,O<:OpType,S,That] (implicit view : S=>scala.collection.Seq[V1], op : BinaryOp[V1,V2,O,RV], c : CompatibleShape[V1,V2], bf : CanBuildFrom[S,RV,That]) : BinaryOp[S,scala.collection.Seq[V2],O,That] = new BinaryOp[S,scala.collection.Seq[V2],O,That] { def opType = op.opType; def apply(a : S, b : scala.collection.Seq[V2]) = { require(a.length == b.length, "Inputs must be the same length"); val builder = bf(a); for ((ai,bi) <- a.iterator zip b.iterator) { builder += op(ai,bi); } builder.result; } } implicit def OpSeqScalar[V1,V2,RV,O<:OpType,S,That] (implicit view : S=>scala.collection.Seq[V1], op : BinaryOp[V1,V2,O,RV], s : Scalar[V2], bf : CanBuildFrom[S,RV,That]) : BinaryOp[S, V2, O, That] = new BinaryOp[S, V2, O, That] { def opType = op.opType; def apply(a : S, b : V2) = { val builder = bf(a); for (v <- a) builder += op(v, b); builder.result; } } implicit def OpScalarSeq[V1,V2,RV,O<:OpType,S,That] (implicit view : S=>scala.collection.Seq[V2], op : BinaryOp[V1,V2,O,RV], s : Scalar[V1], bf : CanBuildFrom[S,RV,That]) : BinaryOp[V1, S, O, That] = new BinaryOp[V1, S, O, That] { def opType = op.opType; def apply(a : V1, b : S) = { val builder = bf(b); for (v <- b) builder += op(a, v); builder.result; } } // // Arrays // implicit def OpArrayArray[V1,V2,RV,O<:OpType] (implicit op : BinaryOp[V1,V2,O,RV], c : CompatibleShape[V1,V2], mf : Manifest[RV]) : BinaryOp[Array[V1],Array[V2],O,Array[RV]] = new BinaryOp[Array[V1],Array[V2],O,Array[RV]] { def opType = op.opType; def apply(a : Array[V1], b : Array[V2]) = { require(a.length == b.length, "Inputs must be the same length"); var rv = new Array[RV](a.length); var i = 0; while (i < rv.length) { rv(i) = op(a(i),b(i)); i += 1; } rv; } } implicit def OpArrayScalar[V1,V2,RV,O<:OpType] (implicit op : BinaryOp[V1,V2,O,RV], s : Scalar[V2], mf : Manifest[RV]) : BinaryOp[Array[V1], V2, O, Array[RV]] = new BinaryOp[Array[V1], V2, O, Array[RV]] { def opType = op.opType; def apply(a : Array[V1], b : V2) = { var rv = new Array[RV](a.length); var i = 0; while (i < rv.length) { rv(i) = op(a(i),b); i += 1; } rv; } } implicit def OpScalarArray[V1,V2,RV,O<:OpType] (implicit op : BinaryOp[V1,V2,O,RV], s : Scalar[V1], mf : Manifest[RV]) : BinaryOp[V1, Array[V2], O, Array[RV]] = new BinaryOp[V1, Array[V2], O, Array[RV]] { def opType = op.opType; def apply(a : V1, b : Array[V2]) = { var rv = new Array[RV](b.length); var i = 0; while (i < rv.length) { rv(i) = op(a,b(i)); i += 1; } rv; } } } ================================================ FILE: src/main/scala/scalala/operators/BinaryOpRegistry.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scala.annotation.implicitNotFound; import scala.collection.generic.CanBuildFrom; import scala.collection.mutable.HashMap; object BinaryOpRegistry { val resultTypes = HashMap[(Manifest[_],Manifest[_],Manifest[_]),Manifest[_]](); val ops = HashMap[(Manifest[_],Manifest[_],Manifest[_]),BinaryOp[_,_,_,_]](); def register[A,B,O<:OpType,To](implicit gen : BinaryOp[A,B,O,To], a : Manifest[A], b : Manifest[B], op : Manifest[O], to : Manifest[To]) = { resultTypes((a,b,op)) = to ops((a,b,op)) = gen } def getResultType[A,B,O<:OpType](implicit a : Manifest[A], b : Manifest[B], op : Manifest[O]) = resultTypes((a,b,op)); def getBinaryOp[A,B,O<:OpType,To](implicit a : Manifest[A], b : Manifest[B], op : Manifest[O], to : Manifest[To]) : BinaryOp[A,B,O,To] = { require(getResultType[A,B,O] == to, "Mismatched result type: "+to); ops((a,b,op)).asInstanceOf[BinaryOp[A,B,O,To]] } } ================================================ FILE: src/main/scala/scalala/operators/BinaryUpdateOp.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scala.annotation.implicitNotFound; import scalala.scalar.Scalar; /** * Operation of type O that updates A using B. Example: A += B. * * @author dramage */ @implicitNotFound(msg="Could not find a way to ${O} ${B} into ${A}") trait BinaryUpdateOp[@specialized -A, @specialized -B, O<:OpType] extends ((A,B) => Unit) { def opType : O; } /** * Very low priority implicits. * * @author dramage */ trait BinaryUpdateOpImplicitsLevel0 { // // Seqs // /** Set mutable seq with corresponding value from another seq. */ implicit def CanSetSeqSeqCast[V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[scala.collection.mutable.Seq[V1], scala.collection.Seq[V2], OpSet] = new BinaryUpdateOp[scala.collection.mutable.Seq[V1], scala.collection.Seq[V2], OpSet] { def opType = OpSet; def apply(a : scala.collection.mutable.Seq[V1], b : scala.collection.Seq[V2]) = { var i = 0; for (v <- b) { a(i) = cast(v); i += 1; } } } /** Set mutable seq with cast scalar. */ implicit def OpSetSeqScalarCast[V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[scala.collection.mutable.Seq[V1], V2, OpSet] = new BinaryUpdateOp[scala.collection.mutable.Seq[V1], V2, OpSet] { def opType = OpSet; def apply(a : scala.collection.mutable.Seq[V1], b : V2) = { val v = cast(b); var i = 0; while (i < a.length) { a(i) = v; i += 1; } } } // // Maps // /** Set mutable map to cast values from another map. */ implicit def OpSetMapMapCast[K,V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[scala.collection.mutable.Map[K,V1], scala.collection.Map[K,V2], OpSet] = new BinaryUpdateOp[scala.collection.mutable.Map[K,V1], scala.collection.Map[K,V2], OpSet] { def opType = OpSet; def apply(a : scala.collection.mutable.Map[K,V1], b : scala.collection.Map[K,V2]) = { for (k <- a.keySet) { a(k) = cast(b.getOrElse(k, s2.zero)); } for (k <- b.keySet) { if (!a.contains(k)) { a(k) = cast(b(k)); } } } } /** Set mutable map to cast scalar. */ implicit def OpSetMapScalarCast[K,V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[scala.collection.mutable.Map[K,V1], V2, OpSet] = new BinaryUpdateOp[scala.collection.mutable.Map[K,V1], V2, OpSet] { def opType = OpSet; def apply(a : scala.collection.mutable.Map[K,V1], b : V2) = { val v = cast(b); for (k <- a.keySet) { a(k) = v; } } } // // Arrays // /** Set array with casted values from another array. */ implicit def OpSetArrayArrayCast[V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[Array[V1],Array[V2], OpSet] = new BinaryUpdateOp[Array[V1],Array[V2], OpSet] { def opType = OpSet; def apply(a : Array[V1], b : Array[V2]) = { var i = 0; while (i < a.length) { a(i) = cast(b(i)); i += 1; } } } /** Set array with casted scalar. */ implicit def OpSetArrayScalarCast[V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[Array[V1],V2,OpSet] = new BinaryUpdateOp[Array[V1],V2,OpSet] { def opType = OpSet; def apply(a : Array[V1], b : V2) = { val v = cast(b); var i = 0; while (i < a.length) { a(i) = v; i += 1; } } } } /** * Low priority implicits. * * @author dramage */ trait BinaryUpdateOpImplicitsLevel1 extends BinaryUpdateOpImplicitsLevel0 { // // Seqs // /** Update mutable seq with corresponding values from another seq. */ implicit def OpUpdateSeqSeq[V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[scala.collection.mutable.Seq[V1], scala.collection.Seq[V2], O] = new BinaryUpdateOp[scala.collection.mutable.Seq[V1], scala.collection.Seq[V2], O] { def opType = op.opType; def apply(a : scala.collection.mutable.Seq[V1], b : scala.collection.Seq[V2]) = { require(a.size == b.size, "Inputs must be the same length"); var i = 0; for (v <- b) { a(i) = op(a(i),v); i += 1; } } } /** Set mutable seq with corresponding value from another seq. */ implicit def OpSetSeqSeq[V](implicit s : Scalar[V]) : BinaryUpdateOp[scala.collection.mutable.Seq[V], scala.collection.Seq[V], OpSet] = new BinaryUpdateOp[scala.collection.mutable.Seq[V], scala.collection.Seq[V], OpSet] { def opType = OpSet; def apply(a : scala.collection.mutable.Seq[V], b : scala.collection.Seq[V]) = { require(a.size == b.size, "Inputs must be the same length"); var i = 0; for (v <- b) { a(i) = v; i += 1; } } } /** Update mutable seq with scalar. */ implicit def OpUpdateSeqScalar[V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], s : Scalar[V2]) : BinaryUpdateOp[scala.collection.mutable.Seq[V1], V2, O] = new BinaryUpdateOp[scala.collection.mutable.Seq[V1], V2, O] { def opType = op.opType; def apply(a : scala.collection.mutable.Seq[V1], b : V2) = { var i = 0; for (v <- a) { a(i) = op(v,b); i += 1; } } } /** Set mutable seq with scalar. */ implicit def OpSetSeqScalar[V](implicit s : Scalar[V]) : BinaryUpdateOp[scala.collection.mutable.Seq[V], V, OpSet] = new BinaryUpdateOp[scala.collection.mutable.Seq[V], V, OpSet] { def opType = OpSet; def apply(a : scala.collection.mutable.Seq[V], b : V) = { var i = 0; while (i < a.length) { a(i) = b; i += 1; } } } // // Maps // /** Update mutable map with corresponding values from another map. */ implicit def OpUpdateMapMap[K,V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[scala.collection.mutable.Map[K,V1], scala.collection.Map[K,V2], O] = new BinaryUpdateOp[scala.collection.mutable.Map[K,V1], scala.collection.Map[K,V2], O] { def opType = op.opType; def apply(a : scala.collection.mutable.Map[K,V1], b : scala.collection.Map[K,V2]) = { for (k <- a.keySet) { a(k) = op(a(k), b.getOrElse(k,s2.zero)); } for (k <- b.keySet) { if (!a.contains(k)) { a(k) = op(s1.zero, b(k)); } } } } /** Set contents of mutable map with corresponding values from another map. */ implicit def OpSetMapMap[K,V](implicit s : Scalar[V]) : BinaryUpdateOp[scala.collection.mutable.Map[K,V], scala.collection.Map[K,V], OpSet] = new BinaryUpdateOp[scala.collection.mutable.Map[K,V], scala.collection.Map[K,V], OpSet] { def opType = OpSet; def apply(a : scala.collection.mutable.Map[K,V], b : scala.collection.Map[K,V]) = { for (k <- a.keySet) { a(k) = b.getOrElse(k,s.zero); } for (k <- b.keySet) { if (!a.contains(k)) { a(k) = b(k); } } } } /** Update mutable map with scalar. */ implicit def OpUpdateMapScalar[K,V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], s : Scalar[V2]) : BinaryUpdateOp[scala.collection.mutable.Map[K,V1], V2, O] = new BinaryUpdateOp[scala.collection.mutable.Map[K,V1], V2, O] { def opType = op.opType; def apply(a : scala.collection.mutable.Map[K,V1], b : V2) = a.transform((k,v) => op(v, b)); } /** Set mutable map to scalar. */ implicit def OpSetMapScalar[K,V](implicit s : Scalar[V]) : BinaryUpdateOp[scala.collection.mutable.Map[K,V], V, OpSet] = new BinaryUpdateOp[scala.collection.mutable.Map[K,V], V, OpSet] { def opType = OpSet; def apply(a : scala.collection.mutable.Map[K,V], b : V) = { for (k <- a.keySet) { a(k) = b; } } } // // Arrays // /** Update array with corresponding values from another array. */ implicit def OpUpdateArrayArray[V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[Array[V1], Array[V2], O] = new BinaryUpdateOp[Array[V1], Array[V2], O] { def opType = op.opType; def apply(a : Array[V1], b : Array[V2]) = { require(a.length == b.length, "Inputs must be the same length"); var i = 0; while (i < a.length) { a(i) = op(a(i),b(i)); i += 1; } } } /** Set array with corresponding values from another array. */ implicit def OpSetArrayArray[V](implicit s : Scalar[V]) : BinaryUpdateOp[Array[V],Array[V],OpSet] = new BinaryUpdateOp[Array[V],Array[V],OpSet] { def opType = OpSet; def apply(a : Array[V], b : Array[V]) = { require(a.length == b.length, "Inputs must be the same length"); System.arraycopy(b, 0, a, 0, a.length); } } /** Update array with scalar. */ implicit def OpUpdateArrayScalar[V1,V2,O<:OpType] (implicit op : BinaryOp[V1,V2,O,V1], s : Scalar[V2]) : BinaryUpdateOp[Array[V1], V2, O] = new BinaryUpdateOp[Array[V1], V2, O] { def opType = op.opType; def apply(a : Array[V1], b : V2) = { var i = 0; while (i < a.length) { a(i) = op(a(i),b); i += 1; } } } /** Set array with scalar. */ implicit def OpSetArrayScalar[V](implicit s : Scalar[V]) : BinaryUpdateOp[Array[V],V,OpSet] = new BinaryUpdateOp[Array[V],V,OpSet] { def opType = OpSet; def apply(a : Array[V], b : V) = { var i = 0; while (i < a.length) { a(i) = b; i += 1; } } } } object BinaryUpdateOp extends BinaryUpdateOpImplicitsLevel1 { // // Tuples // implicit def OpRecurseTuple2Tuple2[VA1,VA2,VB1,VB2,O<:OpType] (implicit op1 : BinaryUpdateOp[VA1,VB1,O], op2 : BinaryUpdateOp[VA2,VB2,O], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2]) : BinaryUpdateOp[(VA1,VA2), (VB1,VB2), O] = new BinaryUpdateOp[(VA1,VA2), (VB1,VB2), O] { def opType = op1.opType; def apply(a : (VA1,VA2), b : (VB1,VB2)) = { op1(a._1,b._1); op2(a._2,b._2); } } implicit def OpRecurseTuple2Scalar[VA1,VA2,VB,O<:OpType] (implicit op1 : BinaryUpdateOp[VA1,VB,O], op2 : BinaryUpdateOp[VA2,VB,O], s : Scalar[VB]) : BinaryUpdateOp[(VA1,VA2), VB, O] = new BinaryUpdateOp[(VA1,VA2), VB, O] { def opType = op1.opType; def apply(a : (VA1,VA2), b : VB) = { op1(a._1,b); op2(a._2,b); } } // // Seqs // /** Recurse on elements within a generic seq. */ implicit def OpRecurseSeqSeq[V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[scala.collection.Seq[V1], scala.collection.Seq[V2], O] = new BinaryUpdateOp[scala.collection.Seq[V1], scala.collection.Seq[V2], O] { def opType = op.opType; def apply(a : scala.collection.Seq[V1], b : scala.collection.Seq[V2]) = { require(a.length == b.length, "Inputs must be the same length"); for ((av,bv) <- (a.iterator zip b.iterator)) { op(av,bv); } } } /** Recurse on elements within a generic seq. */ implicit def OpRecurseSeqScalar[V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], s : Scalar[V2]) : BinaryUpdateOp[scala.collection.Seq[V1], V2, O] = new BinaryUpdateOp[scala.collection.Seq[V1], V2, O] { def opType = op.opType; def apply(a : scala.collection.Seq[V1], b : V2) = { for (v <- a) { op(v, b); } } } // // Maps // /** Recurse on elements within a generic map. */ implicit def OpRecurseMapMap[K,V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[scala.collection.Map[K,V1], scala.collection.Map[K,V2], O] = new BinaryUpdateOp[scala.collection.Map[K,V1], scala.collection.Map[K,V2], O] { def opType = op.opType; def apply(a : scala.collection.Map[K,V1], b : scala.collection.Map[K,V2]) = { for (k <- a.keySet) { op(a(k),b(k)); } for (k <- b.keySet) { if (!a.keySet.contains(k)) { op(a(k),b(k)); } } } } /** Recurse on elements within a generic map. */ implicit def OpRecurseMapScalar[K,V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], s : Scalar[V2]) : BinaryUpdateOp[scala.collection.Map[K,V1], V2, O] = new BinaryUpdateOp[scala.collection.Map[K,V1], V2, O] { def opType = op.opType; def apply(a : scala.collection.Map[K,V1], b : V2) = { for (v <- a.values) { op(v,b); } } } // // Arrays // /** Recurse on elements within an array. */ implicit def OpRecurseArrayArray[V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], c : CompatibleShape[V1,V2]) : BinaryUpdateOp[Array[V1], Array[V2], O] = new BinaryUpdateOp[Array[V1], Array[V2], O] { def opType = op.opType; def apply(a : Array[V1], b : Array[V2]) = { require(a.length == b.length, "Inputs must be the same length"); var i = 0; while (i < a.length) { op(a(i),b(i)); i += 1; } } } implicit def OpRecurseArrayScalar[V1,V2,O<:OpType] (implicit op : BinaryUpdateOp[V1,V2,O], s : Scalar[V2]) : BinaryUpdateOp[Array[V1], V2, O] = new BinaryUpdateOp[Array[V1], V2, O] { def opType = op.opType; def apply(a : Array[V1], b : V2) = { var i = 0; while (i < a.length) { op(a(i),b); i += 1; } } } } ================================================ FILE: src/main/scala/scalala/operators/CanCast.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scala.annotation.implicitNotFound; /** * Cast a value from type A to B. * * @author dramage */ @implicitNotFound(msg="Could not cast ${A} to ${B}") trait CanCast[-A,+B] extends (A => B); object CanCast { implicit object CanCastII extends CanCast[Int,Int] { override def apply(v : Int) = v; } implicit object CanCastIL extends CanCast[Int,Long] { override def apply(v : Int) = v; } implicit object CanCastIF extends CanCast[Int,Float] { override def apply(v : Int) = v; } implicit object CanCastID extends CanCast[Int,Double] { override def apply(v : Int) = v; } implicit object CanCastLL extends CanCast[Long,Long] { override def apply(v : Long) = v; } implicit object CanCastLD extends CanCast[Long,Double] { override def apply(v : Long) = v; } implicit object CanCastFF extends CanCast[Float,Float] { override def apply(v : Float) = v; } implicit object CanCastFD extends CanCast[Float,Double] { override def apply(v : Float) = v; } implicit object CanCastDD extends CanCast[Double,Double] { override def apply(v : Double) = v; } object CanCastIdentityAnyRef extends CanCast[AnyRef,AnyRef] { override def apply(v : AnyRef) = v; } implicit def CanCastIdentity[V] : CanCast[V,V] = CanCastIdentity.asInstanceOf[CanCast[V,V]]; } ================================================ FILE: src/main/scala/scalala/operators/OpType.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scalala.scalar.Scalar; /** * Marker trait for some operation, be it UnaryOp, BinaryOp, or * BinaryUpdateOp. * * @author dramage */ trait OpType; /** * Type marker for BinaryOp A :+ B and BinaryUpdateOp A :+= B. * * @author dramage */ trait OpAdd extends OpType; object OpAdd extends OpAdd; /** * Type marker for BinaryOp A :- B and BinaryUpdateOp A :-= B. * * @author dramage */ trait OpSub extends OpType; object OpSub extends OpSub; /** * Type marker for BinaryOp A :* B and BinaryUpdateOp A :*= B. * * @author dramage */ trait OpMul extends OpType; object OpMul extends OpMul; /** * Type marker for BinaryOp A :/ B and BinaryUpdateOp A:/= B. * * @author dramage */ trait OpDiv extends OpType; object OpDiv extends OpDiv; /** * Type marker for BinaryOp A :% B and BinaryUpdateOp A:%= B. * * @author dramage */ trait OpMod extends OpType; object OpMod extends OpMod; /** * Type marker for BinaryOp A :^ B and BinaryUpdateOp A:^= B. * * @author dramage */ trait OpPow extends OpType; object OpPow extends OpPow; /** * Type marker for BinaryOp A :< B. * * @author dramage */ trait OpLT extends OpType; object OpLT extends OpLT; /** * Type marker for BinaryOp A :<= B. * * @author dramage */ trait OpLTE extends OpType; object OpLTE extends OpLTE; /** * Type marker for BinaryOp A :> B. * * @author dramage */ trait OpGT extends OpType; object OpGT extends OpGT; /** * Type marker for BinaryOp A :>= B. * * @author dramage */ trait OpGTE extends OpType; object OpGTE extends OpGTE; /** * Type marker for BinaryOp A :== B. * * @author dramage */ trait OpEq extends OpType; object OpEq extends OpEq; /** * Type marker for BinaryOp A :!= B. * * @author dramage */ trait OpNe extends OpType; object OpNe extends OpNe; /** * Type marker for BinaryUpdateOp A := B. * * @author dramage */ trait OpSet extends OpType; object OpSet extends OpSet; /** * Type marker for BinaryOp A :&& B * * @author dramage */ trait OpAnd extends OpType; object OpAnd extends OpAnd; /** * Type marker for BinaryOp A :|| B * * @author dramage */ trait OpOr extends OpType; object OpOr extends OpOr; /** * Type marker for BinaryOp A :^^ B * * @author dramage */ trait OpXor extends OpType; object OpXor extends OpXor; /** * Type marker for UnaryOp -A. * * @author dramage */ trait OpNeg extends OpType; object OpNeg extends OpNeg; /** * Type marker for UnaryOp !A. * * @author dramage */ trait OpNot extends OpType; object OpNot extends OpNot; /** * Type marker for inner (dot) product of A and B. * * @author dramage */ trait OpMulInner extends OpType; object OpMulInner extends OpMulInner; /** * Type marker for BinaryOp A * B when A is a row. * * @author dramage */ trait OpMulRowVectorBy extends OpType; object OpMulRowVectorBy extends OpMulRowVectorBy; /** * Type marker for BinaryOp A * B when A is a column. * * @author dramage */ trait OpMulColVectorBy extends OpType; object OpMulColVectorBy extends OpMulColVectorBy; /** * Type marker for BinaryOp A * B when A is a matrix. * * @author dramage */ trait OpMulMatrixBy extends OpType; object OpMulMatrixBy extends OpMulMatrixBy; /** * Type marker for BinaryOp A \ B when A is a matrix. * * @author dramage */ trait OpSolveMatrixBy extends OpType; object OpSolveMatrixBy extends OpSolveMatrixBy; ================================================ FILE: src/main/scala/scalala/operators/Ops.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scalala.scalar.Scalar; import scalala.collection.sparse.{SparseArray,DefaultArrayValue}; /** * Mix-in trait for supporting numeric operators on instances of type This * (accessible with the repr method). * * @author dramage */ trait NumericOps[+This] { def repr : This; def unary_-[TT>:This,That](implicit op : UnaryOp[TT,OpNeg,That]) = op(repr); def unary_![TT>:This,That](implicit op : UnaryOp[TT,OpNot,That]) = op(repr); /** Element-wise sum of this and b. */ def :+ [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpAdd,That]) = op(repr,b); /** Returns the operator delegate used in :+ */ def :+?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpAdd,That]) = op; /** Element-wise difference of this and b. */ def :- [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpSub,That]) = op(repr,b); /** Returns the operator delegate used in :- */ def :-?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpSub,That]) = op; /** Element-wise product of this and b. */ def :* [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMul,That]) = op(repr,b); /** Returns the operator delegate used in :* */ def :*?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMul,That]) = op; /** Element-wise quotient of this and b. */ def :/ [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpDiv,That]) = op(repr,b); /** Returns the operator delegate used in :/ */ def :/?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpDiv,That]) = op; /** Element-wise modulo of this and b. */ def :% [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMod,That]) = op(repr,b); /** Returns the operator delegate used in :% */ def :%?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMod,That]) = op; /** Element-wise exponentiation of this and b. */ def :^ [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpPow,That]) = op(repr,b); /** Returns the operator delegate used in :^ */ def :^?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpPow,That]) = op; /** Element-wise less=than comparator of this and b. */ def :< [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpLT,That]) = op(repr,b); /** Returns the operator delegate used in :< */ def ::This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpLT,That]) = op; /** Element-wise less-than-or-equal-to comparator of this and b. */ def :<= [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpLTE,That]) = op(repr,b); /** Returns the operator delegate used in :<= */ def :<=?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpLTE,That]) = op; /** Element-wise greater-than comparator of this and b. */ def :> [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpGT,That]) = op(repr,b); /** Returns the operator delegate used in :> */ def :>?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpGT,That]) = op; /** Element-wise greater-than-or-equal-to comparator of this and b. */ def :>= [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpGTE,That]) = op(repr,b); /** Returns the operator delegate used in :>= */ def :>=?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpGTE,That]) = op; /** Element-wise equality comparator of this and b. */ def :== [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpEq,That]) = op(repr,b); /** Returns the operator delegate used in :== */ def :==?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpEq,That]) = op; /** Element-wise inequality comparator of this and b. */ def :!= [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpNe,That]) = op(repr,b); /** Returns the operator delegate used in :!= */ def :!=?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpNe,That]) = op; /** Element-wise logical "and" operator -- returns true if corresponding elements are non-zero. */ def :&& [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpAnd,That]) = op(repr,b); /** Returns the operator delegate used in :&& */ def :&&?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpAnd,That]) = op; /** Element-wise logical "or" operator -- returns true if either element is non-zero. */ def :|| [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpOr,That]) = op(repr,b); /** Returns the operator delegate used in :|| */ def :||?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpOr,That]) = op; /** Element-wise logical "xor" operator -- returns true if only one of the corresponding elements is non-zero. */ def :^^ [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpXor,That]) = op(repr,b); /** Returns the operator delegate used in :^^ */ def :^^?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpXor,That]) = op; /** Inner product of this and b. */ def dot [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulInner,That]) = op(repr,b); /** Returns the operator delegate used in dot */ def dotOp[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulInner,That]) = op; // // Operator aliases // /** Alias for :+(b) for all b. */ final def + [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpAdd,That]) = this.:+(b); /** Returns the operator delegate used in + */ final def +?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpAdd,That]) = op; /** Alias for :-(b) for all b. */ final def - [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpSub,That]) = this.:-(b); /** Returns the operator delegate used in - */ final def -?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpSub,That]) = op; /** Alias for :*(b) when b is a scalar. */ final def * [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMul,That], sb : Scalar[B]) = this.:*(b); /** Returns the operator delegate used in * */ final def *?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMul,That], sb : Scalar[B]) = op; /** Alias for :/(b) when b is a scalar. */ final def / [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpDiv,That], sb : Scalar[B]) = this.:/(b); /** Returns the operator delegate used in / */ final def /?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpDiv,That], sb : Scalar[B]) = op; /** Alias for :%(b) when b is a scalar. */ final def % [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMod,That], sb : Scalar[B]) = this.:%(b); /** Returns the operator delegate used in % */ final def %?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMod,That], sb : Scalar[B]) = op; /** Alias for :&&(b) for all b. */ final def && [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpAnd,That]) = this.:&&(b); /** Returns the operator delegate used in && */ final def &&?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpAnd,That]) = op; /** Alias for :||(b) for all b. */ final def || [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpOr,That]) = this.:||(b); /** Returns the operator delegate used in || */ final def ||?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpOr,That]) = op; /** Alias for :^^(b) for all b. */ final def ^^ [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpXor,That]) = this.:^^(b); /** Returns the operator delegate used in ^^ */ final def ^^?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpXor,That]) = op; } /** * Operators for mutable numeric collections. * * @author dramage */ trait MutableNumericOps[+This] extends NumericOps[This] { def repr : This; /** Mutates this by element-wise assignment of b into this. */ def := [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpSet]) : This = { op(repr,b); return repr; } /** Returns the operator delegate used in := */ def :=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpSet]) = op; /** Mutates this by element-wise addition of b into this. */ def :+= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpAdd]) : This = { op(repr,b); return repr; } /** Returns the operator delegate used in :+= */ def :+=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpAdd]) = op; /** Mutates this by element-wise subtraction of b from this */ def :-= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpSub]) : This = { op(repr,b); return repr; } /** Returns the operator delegate used in :-= */ def :-=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpSub]) = op; /** Mutates this by element-wise multiplication of b into this. */ def :*= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpMul]) : This = { op(repr,b); return repr; } /** Returns the operator delegate used in :*= */ def :*=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpMul]) = op; /** Mutates this by element-wise division of b into this */ def :/= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpDiv]) : This = { op(repr,b); return repr; } /** Returns the operator delegate used in :/= */ def :/=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpDiv]) = op; /** Mutates this by element-wise modulo of b into this. */ def :%= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpMod]) : This = { op(repr,b); return repr; } /** Returns the operator delegate used in :%= */ def :%=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpMod]) = op; /** Mutates this by element-wise exponentiation of this by b. */ def :^= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpPow]) : This = { op(repr,b); return repr; } /** Returns the operator delegate used in :^= */ def :^=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpPow]) = op; /** Alias for :+=(b) for all b. */ final def += [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpAdd]) = this.:+=[TT,B](b); /** Returns the operator delegate used in += */ final def +=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpAdd]) = op; /** Alias for :-=(b) for all b. */ final def -= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpSub]) = this.:-=[TT,B](b); /** Returns the operator delegate used in -= */ final def -=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpSub]) = op; /** Alias for :*=(b) when b is a scalar. */ final def *= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpMul], sb : Scalar[B]) = this.:*=[TT,B](b); /** Returns the operator delegate used in *= */ final def *=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpMul], sb : Scalar[B]) = op; /** Alias for :/=(b) when b is a scalar. */ final def /= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpDiv], sb : Scalar[B]) = this.:/=[TT,B](b); /** Returns the operator delegate used in /= */ final def /=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpDiv], sb : Scalar[B]) = op; /** Alias for :%=(b) when b is a scalar. */ final def %= [TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpMod], sb : Scalar[B]) = this.:%=[TT,B](b); /** Returns the operator delegate used in %= */ final def %=?[TT>:This,B](b : B)(implicit op : BinaryUpdateOp[TT,B,OpMod], sb : Scalar[B]) = op; } // // Shaped operations // /** * Secialized shaped numeric operations for columns. * * @author dramage */ trait ColOps[+This] extends NumericOps[This] { /** Shaped multiplication of this by b. */ def * [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulColVectorBy,That]) : That = op(repr, b); /** Returns the operator delegate used in * */ def *?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulColVectorBy,That]) = op; /** A transposed view of this column. */ def t [TT>:This,That](implicit op : CanTranspose[TT,That]) = op.apply(repr); /** Returns the operator delegate used in t */ def tOp[TT>:This,That](implicit op : CanTranspose[TT,That]) = op; } /** * Secialized shaped numeric operations for rows. * * @author dramage */ trait RowOps[+This] extends NumericOps[This] { /** Shaped multiplication of this by b. */ def * [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulRowVectorBy,That]) : That = op(repr, b); /** Returns the operator delegate used in * */ def *?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulRowVectorBy,That]) = op; /** A transposed view of this column. */ def t [TT>:This,That](implicit op : CanTranspose[TT,That]) = op.apply(repr); /** Returns the operator delegate used in t */ def tOp[TT>:This,That](implicit op : CanTranspose[TT,That]) = op; } /** * Provides matrix-like operations for two dimensional collections. * * @author dramage */ trait MatrixOps[+This] extends NumericOps[This] { /** Shaped multiplication of this by b. */ def * [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulMatrixBy,That]) = op.apply(repr,b); /** Returns the operator delegate used in * */ def *?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulMatrixBy,That]) = op; /** Shaped solve of this by b. */ def \ [TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpSolveMatrixBy,That]) = op.apply(repr,b); /** Returns the operator delegate used in \ */ def \?[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpSolveMatrixBy,That]) = op; /** A transposed view of this matrix. */ def t [TT>:This,That](implicit op : CanTranspose[TT,That]) = op.apply(repr); /** Returns the operator delegate used in t */ def tOp[TT>:This,That](implicit op : CanTranspose[TT,That]) = op; } // /** // * Specialized column and row tensor ops for wrapped data structures that // * cannot directly inherit and distinguish between rows and columns in the // * type system. This class assumes unwrapped objects are columns and // * wrapped ones are rows. // * // * @author dramage // */ // trait WrappedColOps[+This] extends NumericOps[This] { // def *[TT>:This,B,That](b : WrappedRowOps[B])(implicit op : BinaryOp[TT,B,OpMulColVectorBy,That]) : That = // op(repr,b.column); // // def t : WrappedRowOps[This] = WrappedRowOps(repr); // } // // /** // * A wrapped column tensor whose underyling collection is mutable. This trait // * should be used instead of mixing in "WrappedColOps with // * MutableNumeriCollectionOps" directly, because .t needs to return an instance // * of MutableRowOps insetad of RowOps. // * // * @author dramage // */ // trait MutableWrappedColOps[+This] extends WrappedColOps[This] with MutableNumericOps[This] { // override def t : MutableWrappedRowOps[This] = MutableWrappedRowOps(repr); // } // // /** // * Secialized NumericOps with shaped operations taking A is a row. // * Note that there is an inherent asymmetry between WrappedColumnTensorOps and // * WrappedRowOps: because tensors are assumed to be columns until reshaped // * (e.g. by calling .t), that class extends NumericOps[A]. This // * class, by contrast, must preserve the fact that the base numeric operations // * like plus must honor the row shape, and that the return result should also // * be a row. Hence this class extends NumericOps[WrappedRowOps[A]] // * and provides implicit magic in the companion object to wrap the // * corresponding construction delegates. // * // * @author dramage // */ // trait WrappedRowOps[+This] extends NumericOps[WrappedRowOps[This]] { // override def repr : WrappedRowOps[This] = this; // // def column : This; // // def *[TT>:This,B,That](b : B)(implicit op : BinaryOp[TT,B,OpMulRowVectorBy,That]) : That = // op(this.column,b); // // /** The transpose returns the underlying value, which assumed to be a column. */ // def t : This = column; // } // // object WrappedRowOps { // def apply[This](v : This) : WrappedRowOps[This] = // new WrappedRowOps[This] { override def column = v; } // // class WrappedRowBinaryOp[A,-B,Op<:OpType,+That](implicit op : BinaryOp[A,B,Op,That]) // extends BinaryOp[WrappedRowOps[A],WrappedRowOps[B],Op,WrappedRowOps[That]] { // override def apply(a : WrappedRowOps[A], b : WrappedRowOps[B]) = // WrappedRowOps(op(a.column,b.column)); // } // // implicit def unwrap[A,B,Op<:OpType,That](implicit op : BinaryOp[A,B,Op,That]) // = new WrappedRowBinaryOp[A,B,Op,That]; // } // // /** // * Specialized WrappedRowOps support for WrappedRows that have mutable // * underlying collections. // * // * @author dramage // */ // trait MutableWrappedRowOps[+This] // extends WrappedRowOps[This] with MutableNumericOps[WrappedRowOps[This]]; // // object MutableWrappedRowOps { // def apply[This](v : This) : MutableWrappedRowOps[This] = // new MutableWrappedRowOps[This] { override def column = v; } // // class MutableWrappedRowBinaryOp[A,-B,Op<:OpType,+That](implicit op : BinaryOp[A,B,Op,That]) // extends BinaryOp[MutableWrappedRowOps[A],WrappedRowOps[B],Op,MutableWrappedRowOps[That]] { // override def apply(a : MutableWrappedRowOps[A], b : WrappedRowOps[B]) = // MutableWrappedRowOps(op(a.column,b.column)); // } // // class MutableWrappedRowBinaryUpdateOp[A,-B,Op<:OpType](implicit op : BinaryUpdateOp[A,B,Op]) // extends BinaryUpdateOp[MutableWrappedRowOps[A],WrappedRowOps[B],Op] { // override def apply(a : MutableWrappedRowOps[A], b : WrappedRowOps[B]) = // op(a.column, b.column); // } // // implicit def unwrapBinaryOp[A,B,Op<:OpType,That](implicit op : BinaryOp[A,B,Op,That]) // = new MutableWrappedRowBinaryOp[A,B,Op,That]; // // implicit def unwrapBinaryUpdateOp[A,B,Op<:OpType](implicit op : BinaryUpdateOp[A,B,Op]) // = new MutableWrappedRowBinaryUpdateOp[A,B,Op]; // } /** * Numeric operator support for numeric arrays. * * @author dramage */ class RichArrayVector[V:ClassManifest](override val repr : Array[V]) extends MutableNumericOps[Array[V]] { //extends MutableWrappedColOps[Array[V]] { /** Returns a vector view of this array. */ def asVector(implicit s : Scalar[V]) = new scalala.tensor.dense.DenseVectorCol(repr); } /** * Numeric operator support for Array[Array] matrix. * * @author dramage */ class RichArrayMatrix[V:ClassManifest](override val repr : Array[Array[V]]) extends MutableNumericOps[Array[Array[V]]] { //extends MatrixOps[Array[Array[V]]] { /** Returns a matrix view of this array. */ def asMatrix(implicit s : Scalar[V]) = new scalala.tensor.dense.ArrayArrayMatrix(repr); } /** * Numeric operator support for SparseArray vector. * * @author dramage */ class RichSparseArrayVector[V:ClassManifest:DefaultArrayValue](override val repr : SparseArray[V]) extends MutableNumericOps[SparseArray[V]] { //extends MutableWrappedColOps[SparseArray[V]] { /** Returns a vector view of this sparse array. */ def asVector(implicit s : Scalar[V]) = new scalala.tensor.sparse.SparseVectorCol(repr); } /** * Numeric operator support for solo scalars. Note: raw + is ambiguous * with the any2String implicit that comes built in with scala and is used for string concatenation. Use :+ instead. * * @author dramage */ class RichScalar[@specialized V:Scalar](override val repr : V) extends NumericOps[V] { /** This is a scalar, so alias for :*(b) for all b. */ final def *[B,That](b : B)(implicit op : BinaryOp[V,B,OpMul,That]) = this.:*(b); /** This is a scalar, so alias for :/(b) for all b. */ final def /[B,That](b : B)(implicit op : BinaryOp[V,B,OpDiv,That]) = this.:/(b); /** This is a scalar, so alias for :%(b) for all b. */ final def %[B,That](b : B)(implicit op : BinaryOp[V,B,OpMod,That]) = this.:%(b); } /** * Adds rich math operators to a map. Adds mutable as well as * immutable operators because inner data structures may be mutable. * * @author dramage */ class RichMap[M<:scala.collection.Map[_,_]](override val repr : M) extends MutableNumericOps[M]; /** * Adds rich math operators to a seq. Adds mutable as well as * immutable operators because inner data structures may be mutable. * * @author dramage */ class RichSeq[S<:scala.collection.Seq[_]](override val repr : S) extends MutableNumericOps[S] { // TODO: add me when we can reliably get the value type from the collection // // /** Constructs a new vector view of this sequence. */ // def toVector(implicit s : Scalar[V]) = { // implicit val mf = s.manifest; // new RichArray(repr.toArray).asVector; // } // // /** // * Constructs a new matrix view of this sequence. // * If only one of rows or cols is specified, infers the other. // */ // def toMatrix(rows : Int = -1, cols : Int = -1)(implicit s : Scalar[V]) = { // implicit val mf = s.manifest; // new RichArray(repr.toArray).asMatrix(rows, cols); // } } /** * Adds rich math operators to an array. * * @author dramage */ class RichArray[@specialized V](override val repr : Array[V]) extends MutableNumericOps[Array[V]] { /** Constructs a view of this array as a column vector. */ def asVector(implicit s : Scalar[V]) = new scalala.tensor.dense.DenseVectorCol(repr); /** * Constructs a view of this array as a matrix of the given dimensions. * If only one of rows or cols is specified, infers the other. */ def asMatrix(rows : Int = -1, cols : Int = -1)(implicit s : Scalar[V]) = { require(rows > 0 || cols > 0, "Must specify either rows or cols to view as matrix."); val r = if (rows >= 0) rows else { require(repr.length % cols == 0, "Input length does not evenly divide by requested number of cols"); repr.length / cols; }; val c = if (cols >= 0) cols else { require(repr.length % rows == 0, "Input length does not evenly divide by requested number of rows"); repr.length / rows; }; new scalala.tensor.dense.DenseMatrix(r, c, repr); } } /** * Adds rich math operators to functions. * * @author dramage */ class RichFunction2[@specialized A, @specialized B](override val repr : A=>B) extends NumericOps[A=>B] { def :@[VV,That](values : VV)(implicit bf : scala.collection.generic.CanBuildFrom[VV,B,That], vv : VV => TraversableOnce[A]) = { val rv = bf(values); for (v <- values) rv += repr(v); rv.result; } } trait ImplicitsLevel0 { implicit def richScalar[@specialized V:Scalar](value : V) = new RichScalar(value); } trait ImplicitsLevel1 extends ImplicitsLevel0 { implicit def richMap[M<:scala.collection.Map[_,_]](map : M) = new RichMap(map); implicit def richSeq[S<:scala.collection.Seq[_]](seq : S) = new RichSeq(seq); implicit def richArray[@specialized V:Scalar](arr : Array[V]) = new RichArray(arr); } /** * Implicit promotions of built-in scala types to enriched numerically valued * equivalents. After importing the members of this class, you can directly * do math on all tuples, arrays, and maps. * * @author dramage */ object Implicits extends RichTupleImplicits with ImplicitsLevel1 { implicit def richArrayMatrix[@specialized V:Scalar:ClassManifest](arr : Array[Array[V]]) = new RichArrayMatrix(arr); } ================================================ FILE: src/main/scala/scalala/operators/Shape.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scala.annotation.implicitNotFound; import scalala.scalar.Scalar; /** * Marker trait describing the shape of a value V as having * shape signature S. This class is never instantiated and * is used only as an implicit to ensure compatibility between * shapes of arguments when operating on collections. * * @author dramage */ @implicitNotFound(msg="Could not recover shape of ${V}") trait Shape[-V,S]; trait LowPriorityShapeImplicits { /** Arbitrary objects have shape Unit. */ @inline implicit def any[V] : Shape[V,Unit] = null; } object Shape extends LowPriorityShapeImplicits { def apply[V,S](v : V)(implicit shape : Shape[V,S]) = shape; /** Tuples have shape (Unit,Unit, ...). */ @inline implicit def tuple2[V1,V2] : Shape[(V1,V2),(Unit,Unit)] = null; /** Tuples have shape (Unit,Unit, ...). */ @inline implicit def tuple3[V1,V2,V3] : Shape[(V1,V2,V3),(Unit,Unit,Unit)] = null; /** Tuples have shape (Unit,Unit, ...). */ @inline implicit def tuple4[V1,V2,V3,V4] : Shape[(V1,V2,V3,V4),(Unit,Unit,Unit,Unit)] = null; // TODO: add more tuples /** Maps have shape (KeyShape=>ValueShape). */ @inline implicit def map[K,KeyShape,V,ValueShape] (implicit kShape : Shape[K,KeyShape], vShape : Shape[V,ValueShape]) : Shape[scala.collection.Map[K,V],(KeyShape=>ValueShape)] = null; /** Seqs have shape (Unit=>ValueShape). */ @inline implicit def seq[V,ValueShape](implicit vShape : Shape[V,ValueShape]) : Shape[scala.collection.Seq[V],(Unit=>ValueShape)] = null; /** Arrays have shape (Unit=>ValueShape). */ @inline implicit def array[V,ValueShape](implicit vShape : Shape[V,ValueShape]) : Shape[Array[V],(Unit=>ValueShape)] = null; } /** * Marker trait that says that A and B have statically * compatible shape. This trait is never instantiated and is * used only as an implicit to ensure that types A and B have * compatible shapes for performing operations. * * @author dramage */ @implicitNotFound(msg="Types ${A} and ${B} have incompatible shape") sealed trait CompatibleShape[A,B] object CompatibleShape { @inline implicit def apply[A,SA,B,SB] (implicit sa : Shape[A,SA], sb : Shape[B,SB], eq : =:=[SA,SB]) : CompatibleShape[A,B] = null; } ================================================ FILE: src/main/scala/scalala/operators/TupleOps.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scalala.scalar.Scalar; // The contents of this file were automatically generated: // println("trait UnaryTupleOps {"); // for (n <- 2 to 22) { // val va = (1 to n).map("VA"+_).mkString(","); // val rv = (1 to n).map("RV"+_).mkString(","); // val ops = (1 to n).map(i => "op! : UnaryOp[VA!,O,RV!]".replaceAll("!",""+i)).mkString(", "); // val code = (1 to n).map(i => "op!(v._!)".replaceAll("!",""+i)).mkString(", "); // val unaryOp = // """ // implicit def OpTuple%d[%s,%s,O<:OpType] // (implicit %s) // : UnaryOp[(%s),O,(%s)] // = new UnaryOp[(%s),O,(%s)] { // def opType = op1.opType; // def apply(v : (%s)) = (%s); // } // """.format(n,va,rv,ops,va,rv,va,rv,va,code); // print(unaryOp); // } // println("}"); // // println("trait BinaryTupleOps {"); // for (n <- 2 to 22) { // val va = (1 to n).map("VA"+_).mkString(","); // val vb = (1 to n).map("VB"+_).mkString(","); // val rv = (1 to n).map("RV"+_).mkString(","); // // val opsTupleTuple = (1 to n).map(i => "op! : BinaryOp[VA!,VB!,O,RV!]".replaceAll("!",""+i)).mkString(", "); // val shapesTupleTuple = (1 to n).map(i => "c! : CompatibleShape[VA!,VB!]".replaceAll("!",""+i)).mkString(", "); // val valueTupleTuple = (1 to n).map(i => "op!(a._!,b._!)".replaceAll("!",""+i)).mkString(", "); // val codeTupleTuple = // """ // implicit def OpTuple%dTuple%d[%s,%s,%s,O<:OpType] // (implicit %s, %s) // : BinaryOp[(%s),(%s),O,(%s)] // = new BinaryOp[(%s),(%s),O,(%s)] { // def opType = op1.opType; // def apply(a : (%s), b : (%s)) = (%s); // } // """.format(n, n, va, vb, rv, opsTupleTuple, shapesTupleTuple, va, vb, rv, va, vb, rv, va, vb, valueTupleTuple); // // val opsTupleScalar = (1 to n).map(i => "op! : BinaryOp[VA!,VS,O,RV!]".replaceAll("!",""+i)).mkString(", "); // val valueTupleScalar = (1 to n).map(i => "op!(a._!,s)".replaceAll("!",""+i)).mkString(", "); // val codeTupleScalar = // """ // implicit def OpTuple%dScalar[%s,VS,%s,O<:OpType] // (implicit %s, s : Scalar[VS]) // : BinaryOp[(%s),VS,O,(%s)] // = new BinaryOp[(%s),VS,O,(%s)] { // def opType = op1.opType; // def apply(a : (%s), s : VS) = (%s); // } // """.format(n, va, rv, opsTupleScalar, va, rv, va, rv, va, valueTupleScalar); // // val opsScalarTuple = (1 to n).map(i => "op! : BinaryOp[VS,VB!,O,RV!]".replaceAll("!",""+i)).mkString(", "); // val valueScalarTuple = (1 to n).map(i => "op!(s,b._!)".replaceAll("!",""+i)).mkString(", "); // val codeScalarTuple = // """ // implicit def OpScalarTuple%d[VS,%s,%s,O<:OpType] // (implicit %s, s : Scalar[VS]) // : BinaryOp[VS,(%s),O,(%s)] // = new BinaryOp[VS,(%s),O,(%s)] { // def opType = op1.opType; // def apply(s : VS, b : (%s)) = (%s); // } // """.format(n, vb, rv, opsScalarTuple, vb, rv, vb, rv, vb, valueScalarTuple); // // print(codeTupleTuple); // print(codeTupleScalar); // print(codeScalarTuple); // } // println("}"); // // println("object RichTuples {"); // for (n <- 2 to 22) { // val tupArg = (1 to n).map((if (n <= 3) "@specialized V" else "V") + _).mkString(", "); // val tupVal = (1 to n).map("V"+_).mkString(","); // println( // " class RichTuple%d[%s](override val repr : (%s)) extends MutableNumericOps[(%s)];\n" // .format(n,tupArg,tupVal,tupVal) // ); // } // println("}\n\n"); // // println("trait RichTupleImplicits {"); // println(" import RichTuples._"); // for (n <- 2 to 22) { // val tupArg = (1 to n).map((if (n <= 3) "@specialized V" else "V") + _).mkString(", "); // val tupVal = (1 to n).map("V"+_).mkString(","); // println( // " implicit def richTuple%d[%s](value : (%s)) = new RichTuple%d(value);\n" // .format(n,tupArg,tupVal,n) // ); // } // println("}\n"); /** * Unary operations on tensors of arity 2 to 22. * * @author dramage */ trait UnaryTupleOps { implicit def OpTuple2[VA1,VA2,RV1,RV2,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2]) : UnaryOp[(VA1,VA2),O,(RV1,RV2)] = new UnaryOp[(VA1,VA2),O,(RV1,RV2)] { def opType = op1.opType; def apply(v : (VA1,VA2)) = (op1(v._1), op2(v._2)); } implicit def OpTuple3[VA1,VA2,VA3,RV1,RV2,RV3,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3]) : UnaryOp[(VA1,VA2,VA3),O,(RV1,RV2,RV3)] = new UnaryOp[(VA1,VA2,VA3),O,(RV1,RV2,RV3)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3)) = (op1(v._1), op2(v._2), op3(v._3)); } implicit def OpTuple4[VA1,VA2,VA3,VA4,RV1,RV2,RV3,RV4,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4]) : UnaryOp[(VA1,VA2,VA3,VA4),O,(RV1,RV2,RV3,RV4)] = new UnaryOp[(VA1,VA2,VA3,VA4),O,(RV1,RV2,RV3,RV4)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4)); } implicit def OpTuple5[VA1,VA2,VA3,VA4,VA5,RV1,RV2,RV3,RV4,RV5,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5),O,(RV1,RV2,RV3,RV4,RV5)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5),O,(RV1,RV2,RV3,RV4,RV5)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5)); } implicit def OpTuple6[VA1,VA2,VA3,VA4,VA5,VA6,RV1,RV2,RV3,RV4,RV5,RV6,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6),O,(RV1,RV2,RV3,RV4,RV5,RV6)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6),O,(RV1,RV2,RV3,RV4,RV5,RV6)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6)); } implicit def OpTuple7[VA1,VA2,VA3,VA4,VA5,VA6,VA7,RV1,RV2,RV3,RV4,RV5,RV6,RV7,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7)); } implicit def OpTuple8[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8)); } implicit def OpTuple9[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9)); } implicit def OpTuple10[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10)); } implicit def OpTuple11[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11)); } implicit def OpTuple12[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12)); } implicit def OpTuple13[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13)); } implicit def OpTuple14[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14)); } implicit def OpTuple15[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14], op15 : UnaryOp[VA15,O,RV15]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14), op15(v._15)); } implicit def OpTuple16[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14], op15 : UnaryOp[VA15,O,RV15], op16 : UnaryOp[VA16,O,RV16]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14), op15(v._15), op16(v._16)); } implicit def OpTuple17[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14], op15 : UnaryOp[VA15,O,RV15], op16 : UnaryOp[VA16,O,RV16], op17 : UnaryOp[VA17,O,RV17]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14), op15(v._15), op16(v._16), op17(v._17)); } implicit def OpTuple18[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14], op15 : UnaryOp[VA15,O,RV15], op16 : UnaryOp[VA16,O,RV16], op17 : UnaryOp[VA17,O,RV17], op18 : UnaryOp[VA18,O,RV18]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14), op15(v._15), op16(v._16), op17(v._17), op18(v._18)); } implicit def OpTuple19[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14], op15 : UnaryOp[VA15,O,RV15], op16 : UnaryOp[VA16,O,RV16], op17 : UnaryOp[VA17,O,RV17], op18 : UnaryOp[VA18,O,RV18], op19 : UnaryOp[VA19,O,RV19]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14), op15(v._15), op16(v._16), op17(v._17), op18(v._18), op19(v._19)); } implicit def OpTuple20[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14], op15 : UnaryOp[VA15,O,RV15], op16 : UnaryOp[VA16,O,RV16], op17 : UnaryOp[VA17,O,RV17], op18 : UnaryOp[VA18,O,RV18], op19 : UnaryOp[VA19,O,RV19], op20 : UnaryOp[VA20,O,RV20]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14), op15(v._15), op16(v._16), op17(v._17), op18(v._18), op19(v._19), op20(v._20)); } implicit def OpTuple21[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14], op15 : UnaryOp[VA15,O,RV15], op16 : UnaryOp[VA16,O,RV16], op17 : UnaryOp[VA17,O,RV17], op18 : UnaryOp[VA18,O,RV18], op19 : UnaryOp[VA19,O,RV19], op20 : UnaryOp[VA20,O,RV20], op21 : UnaryOp[VA21,O,RV21]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14), op15(v._15), op16(v._16), op17(v._17), op18(v._18), op19(v._19), op20(v._20), op21(v._21)); } implicit def OpTuple22[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22,O<:OpType] (implicit op1 : UnaryOp[VA1,O,RV1], op2 : UnaryOp[VA2,O,RV2], op3 : UnaryOp[VA3,O,RV3], op4 : UnaryOp[VA4,O,RV4], op5 : UnaryOp[VA5,O,RV5], op6 : UnaryOp[VA6,O,RV6], op7 : UnaryOp[VA7,O,RV7], op8 : UnaryOp[VA8,O,RV8], op9 : UnaryOp[VA9,O,RV9], op10 : UnaryOp[VA10,O,RV10], op11 : UnaryOp[VA11,O,RV11], op12 : UnaryOp[VA12,O,RV12], op13 : UnaryOp[VA13,O,RV13], op14 : UnaryOp[VA14,O,RV14], op15 : UnaryOp[VA15,O,RV15], op16 : UnaryOp[VA16,O,RV16], op17 : UnaryOp[VA17,O,RV17], op18 : UnaryOp[VA18,O,RV18], op19 : UnaryOp[VA19,O,RV19], op20 : UnaryOp[VA20,O,RV20], op21 : UnaryOp[VA21,O,RV21], op22 : UnaryOp[VA22,O,RV22]) : UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22)] = new UnaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22)] { def opType = op1.opType; def apply(v : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22)) = (op1(v._1), op2(v._2), op3(v._3), op4(v._4), op5(v._5), op6(v._6), op7(v._7), op8(v._8), op9(v._9), op10(v._10), op11(v._11), op12(v._12), op13(v._13), op14(v._14), op15(v._15), op16(v._16), op17(v._17), op18(v._18), op19(v._19), op20(v._20), op21(v._21), op22(v._22)); } } /** * Binary operator support for tuples of aritys 2 to 22. * * @author dramage */ trait BinaryTupleOps { implicit def OpTuple2Tuple2[VA1,VA2,VB1,VB2,RV1,RV2,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2]) : BinaryOp[(VA1,VA2),(VB1,VB2),O,(RV1,RV2)] = new BinaryOp[(VA1,VA2),(VB1,VB2),O,(RV1,RV2)] { def opType = op1.opType; def apply(a : (VA1,VA2), b : (VB1,VB2)) = (op1(a._1,b._1), op2(a._2,b._2)); } implicit def OpTuple2Scalar[VA1,VA2,VS,RV1,RV2,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], s : Scalar[VS]) : BinaryOp[(VA1,VA2),VS,O,(RV1,RV2)] = new BinaryOp[(VA1,VA2),VS,O,(RV1,RV2)] { def opType = op1.opType; def apply(a : (VA1,VA2), s : VS) = (op1(a._1,s), op2(a._2,s)); } implicit def OpScalarTuple2[VS,VB1,VB2,RV1,RV2,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2),O,(RV1,RV2)] = new BinaryOp[VS,(VB1,VB2),O,(RV1,RV2)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2)) = (op1(s,b._1), op2(s,b._2)); } implicit def OpTuple3Tuple3[VA1,VA2,VA3,VB1,VB2,VB3,RV1,RV2,RV3,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3]) : BinaryOp[(VA1,VA2,VA3),(VB1,VB2,VB3),O,(RV1,RV2,RV3)] = new BinaryOp[(VA1,VA2,VA3),(VB1,VB2,VB3),O,(RV1,RV2,RV3)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3), b : (VB1,VB2,VB3)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3)); } implicit def OpTuple3Scalar[VA1,VA2,VA3,VS,RV1,RV2,RV3,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3),VS,O,(RV1,RV2,RV3)] = new BinaryOp[(VA1,VA2,VA3),VS,O,(RV1,RV2,RV3)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s)); } implicit def OpScalarTuple3[VS,VB1,VB2,VB3,RV1,RV2,RV3,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3),O,(RV1,RV2,RV3)] = new BinaryOp[VS,(VB1,VB2,VB3),O,(RV1,RV2,RV3)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3)); } implicit def OpTuple4Tuple4[VA1,VA2,VA3,VA4,VB1,VB2,VB3,VB4,RV1,RV2,RV3,RV4,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4]) : BinaryOp[(VA1,VA2,VA3,VA4),(VB1,VB2,VB3,VB4),O,(RV1,RV2,RV3,RV4)] = new BinaryOp[(VA1,VA2,VA3,VA4),(VB1,VB2,VB3,VB4),O,(RV1,RV2,RV3,RV4)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4), b : (VB1,VB2,VB3,VB4)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4)); } implicit def OpTuple4Scalar[VA1,VA2,VA3,VA4,VS,RV1,RV2,RV3,RV4,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4),VS,O,(RV1,RV2,RV3,RV4)] = new BinaryOp[(VA1,VA2,VA3,VA4),VS,O,(RV1,RV2,RV3,RV4)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s)); } implicit def OpScalarTuple4[VS,VB1,VB2,VB3,VB4,RV1,RV2,RV3,RV4,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4),O,(RV1,RV2,RV3,RV4)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4),O,(RV1,RV2,RV3,RV4)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4)); } implicit def OpTuple5Tuple5[VA1,VA2,VA3,VA4,VA5,VB1,VB2,VB3,VB4,VB5,RV1,RV2,RV3,RV4,RV5,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5),(VB1,VB2,VB3,VB4,VB5),O,(RV1,RV2,RV3,RV4,RV5)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5),(VB1,VB2,VB3,VB4,VB5),O,(RV1,RV2,RV3,RV4,RV5)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5), b : (VB1,VB2,VB3,VB4,VB5)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5)); } implicit def OpTuple5Scalar[VA1,VA2,VA3,VA4,VA5,VS,RV1,RV2,RV3,RV4,RV5,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5),VS,O,(RV1,RV2,RV3,RV4,RV5)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5),VS,O,(RV1,RV2,RV3,RV4,RV5)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s)); } implicit def OpScalarTuple5[VS,VB1,VB2,VB3,VB4,VB5,RV1,RV2,RV3,RV4,RV5,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5),O,(RV1,RV2,RV3,RV4,RV5)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5),O,(RV1,RV2,RV3,RV4,RV5)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5)); } implicit def OpTuple6Tuple6[VA1,VA2,VA3,VA4,VA5,VA6,VB1,VB2,VB3,VB4,VB5,VB6,RV1,RV2,RV3,RV4,RV5,RV6,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6),(VB1,VB2,VB3,VB4,VB5,VB6),O,(RV1,RV2,RV3,RV4,RV5,RV6)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6),(VB1,VB2,VB3,VB4,VB5,VB6),O,(RV1,RV2,RV3,RV4,RV5,RV6)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6), b : (VB1,VB2,VB3,VB4,VB5,VB6)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6)); } implicit def OpTuple6Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VS,RV1,RV2,RV3,RV4,RV5,RV6,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s)); } implicit def OpScalarTuple6[VS,VB1,VB2,VB3,VB4,VB5,VB6,RV1,RV2,RV3,RV4,RV5,RV6,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6),O,(RV1,RV2,RV3,RV4,RV5,RV6)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6),O,(RV1,RV2,RV3,RV4,RV5,RV6)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6)); } implicit def OpTuple7Tuple7[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VB1,VB2,VB3,VB4,VB5,VB6,VB7,RV1,RV2,RV3,RV4,RV5,RV6,RV7,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7),(VB1,VB2,VB3,VB4,VB5,VB6,VB7),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7),(VB1,VB2,VB3,VB4,VB5,VB6,VB7),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7)); } implicit def OpTuple7Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s)); } implicit def OpScalarTuple7[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,RV1,RV2,RV3,RV4,RV5,RV6,RV7,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7)); } implicit def OpTuple8Tuple8[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8)); } implicit def OpTuple8Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s)); } implicit def OpScalarTuple8[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8)); } implicit def OpTuple9Tuple9[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9)); } implicit def OpTuple9Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s)); } implicit def OpScalarTuple9[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9)); } implicit def OpTuple10Tuple10[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10)); } implicit def OpTuple10Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s)); } implicit def OpScalarTuple10[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10)); } implicit def OpTuple11Tuple11[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11)); } implicit def OpTuple11Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s)); } implicit def OpScalarTuple11[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11)); } implicit def OpTuple12Tuple12[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12)); } implicit def OpTuple12Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s)); } implicit def OpScalarTuple12[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12)); } implicit def OpTuple13Tuple13[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13)); } implicit def OpTuple13Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s)); } implicit def OpScalarTuple13[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13)); } implicit def OpTuple14Tuple14[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14)); } implicit def OpTuple14Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s)); } implicit def OpScalarTuple14[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14)); } implicit def OpTuple15Tuple15[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], op15 : BinaryOp[VA15,VB15,O,RV15], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14], c15 : CompatibleShape[VA15,VB15]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14), op15(a._15,b._15)); } implicit def OpTuple15Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], op15 : BinaryOp[VA15,VS,O,RV15], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s), op15(a._15,s)); } implicit def OpScalarTuple15[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], op15 : BinaryOp[VS,VB15,O,RV15], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14), op15(s,b._15)); } implicit def OpTuple16Tuple16[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], op15 : BinaryOp[VA15,VB15,O,RV15], op16 : BinaryOp[VA16,VB16,O,RV16], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14], c15 : CompatibleShape[VA15,VB15], c16 : CompatibleShape[VA16,VB16]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14), op15(a._15,b._15), op16(a._16,b._16)); } implicit def OpTuple16Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], op15 : BinaryOp[VA15,VS,O,RV15], op16 : BinaryOp[VA16,VS,O,RV16], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s), op15(a._15,s), op16(a._16,s)); } implicit def OpScalarTuple16[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], op15 : BinaryOp[VS,VB15,O,RV15], op16 : BinaryOp[VS,VB16,O,RV16], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14), op15(s,b._15), op16(s,b._16)); } implicit def OpTuple17Tuple17[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], op15 : BinaryOp[VA15,VB15,O,RV15], op16 : BinaryOp[VA16,VB16,O,RV16], op17 : BinaryOp[VA17,VB17,O,RV17], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14], c15 : CompatibleShape[VA15,VB15], c16 : CompatibleShape[VA16,VB16], c17 : CompatibleShape[VA17,VB17]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14), op15(a._15,b._15), op16(a._16,b._16), op17(a._17,b._17)); } implicit def OpTuple17Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], op15 : BinaryOp[VA15,VS,O,RV15], op16 : BinaryOp[VA16,VS,O,RV16], op17 : BinaryOp[VA17,VS,O,RV17], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s), op15(a._15,s), op16(a._16,s), op17(a._17,s)); } implicit def OpScalarTuple17[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], op15 : BinaryOp[VS,VB15,O,RV15], op16 : BinaryOp[VS,VB16,O,RV16], op17 : BinaryOp[VS,VB17,O,RV17], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14), op15(s,b._15), op16(s,b._16), op17(s,b._17)); } implicit def OpTuple18Tuple18[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], op15 : BinaryOp[VA15,VB15,O,RV15], op16 : BinaryOp[VA16,VB16,O,RV16], op17 : BinaryOp[VA17,VB17,O,RV17], op18 : BinaryOp[VA18,VB18,O,RV18], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14], c15 : CompatibleShape[VA15,VB15], c16 : CompatibleShape[VA16,VB16], c17 : CompatibleShape[VA17,VB17], c18 : CompatibleShape[VA18,VB18]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14), op15(a._15,b._15), op16(a._16,b._16), op17(a._17,b._17), op18(a._18,b._18)); } implicit def OpTuple18Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], op15 : BinaryOp[VA15,VS,O,RV15], op16 : BinaryOp[VA16,VS,O,RV16], op17 : BinaryOp[VA17,VS,O,RV17], op18 : BinaryOp[VA18,VS,O,RV18], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s), op15(a._15,s), op16(a._16,s), op17(a._17,s), op18(a._18,s)); } implicit def OpScalarTuple18[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], op15 : BinaryOp[VS,VB15,O,RV15], op16 : BinaryOp[VS,VB16,O,RV16], op17 : BinaryOp[VS,VB17,O,RV17], op18 : BinaryOp[VS,VB18,O,RV18], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14), op15(s,b._15), op16(s,b._16), op17(s,b._17), op18(s,b._18)); } implicit def OpTuple19Tuple19[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], op15 : BinaryOp[VA15,VB15,O,RV15], op16 : BinaryOp[VA16,VB16,O,RV16], op17 : BinaryOp[VA17,VB17,O,RV17], op18 : BinaryOp[VA18,VB18,O,RV18], op19 : BinaryOp[VA19,VB19,O,RV19], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14], c15 : CompatibleShape[VA15,VB15], c16 : CompatibleShape[VA16,VB16], c17 : CompatibleShape[VA17,VB17], c18 : CompatibleShape[VA18,VB18], c19 : CompatibleShape[VA19,VB19]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14), op15(a._15,b._15), op16(a._16,b._16), op17(a._17,b._17), op18(a._18,b._18), op19(a._19,b._19)); } implicit def OpTuple19Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], op15 : BinaryOp[VA15,VS,O,RV15], op16 : BinaryOp[VA16,VS,O,RV16], op17 : BinaryOp[VA17,VS,O,RV17], op18 : BinaryOp[VA18,VS,O,RV18], op19 : BinaryOp[VA19,VS,O,RV19], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s), op15(a._15,s), op16(a._16,s), op17(a._17,s), op18(a._18,s), op19(a._19,s)); } implicit def OpScalarTuple19[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], op15 : BinaryOp[VS,VB15,O,RV15], op16 : BinaryOp[VS,VB16,O,RV16], op17 : BinaryOp[VS,VB17,O,RV17], op18 : BinaryOp[VS,VB18,O,RV18], op19 : BinaryOp[VS,VB19,O,RV19], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14), op15(s,b._15), op16(s,b._16), op17(s,b._17), op18(s,b._18), op19(s,b._19)); } implicit def OpTuple20Tuple20[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], op15 : BinaryOp[VA15,VB15,O,RV15], op16 : BinaryOp[VA16,VB16,O,RV16], op17 : BinaryOp[VA17,VB17,O,RV17], op18 : BinaryOp[VA18,VB18,O,RV18], op19 : BinaryOp[VA19,VB19,O,RV19], op20 : BinaryOp[VA20,VB20,O,RV20], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14], c15 : CompatibleShape[VA15,VB15], c16 : CompatibleShape[VA16,VB16], c17 : CompatibleShape[VA17,VB17], c18 : CompatibleShape[VA18,VB18], c19 : CompatibleShape[VA19,VB19], c20 : CompatibleShape[VA20,VB20]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14), op15(a._15,b._15), op16(a._16,b._16), op17(a._17,b._17), op18(a._18,b._18), op19(a._19,b._19), op20(a._20,b._20)); } implicit def OpTuple20Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], op15 : BinaryOp[VA15,VS,O,RV15], op16 : BinaryOp[VA16,VS,O,RV16], op17 : BinaryOp[VA17,VS,O,RV17], op18 : BinaryOp[VA18,VS,O,RV18], op19 : BinaryOp[VA19,VS,O,RV19], op20 : BinaryOp[VA20,VS,O,RV20], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s), op15(a._15,s), op16(a._16,s), op17(a._17,s), op18(a._18,s), op19(a._19,s), op20(a._20,s)); } implicit def OpScalarTuple20[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], op15 : BinaryOp[VS,VB15,O,RV15], op16 : BinaryOp[VS,VB16,O,RV16], op17 : BinaryOp[VS,VB17,O,RV17], op18 : BinaryOp[VS,VB18,O,RV18], op19 : BinaryOp[VS,VB19,O,RV19], op20 : BinaryOp[VS,VB20,O,RV20], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14), op15(s,b._15), op16(s,b._16), op17(s,b._17), op18(s,b._18), op19(s,b._19), op20(s,b._20)); } implicit def OpTuple21Tuple21[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], op15 : BinaryOp[VA15,VB15,O,RV15], op16 : BinaryOp[VA16,VB16,O,RV16], op17 : BinaryOp[VA17,VB17,O,RV17], op18 : BinaryOp[VA18,VB18,O,RV18], op19 : BinaryOp[VA19,VB19,O,RV19], op20 : BinaryOp[VA20,VB20,O,RV20], op21 : BinaryOp[VA21,VB21,O,RV21], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14], c15 : CompatibleShape[VA15,VB15], c16 : CompatibleShape[VA16,VB16], c17 : CompatibleShape[VA17,VB17], c18 : CompatibleShape[VA18,VB18], c19 : CompatibleShape[VA19,VB19], c20 : CompatibleShape[VA20,VB20], c21 : CompatibleShape[VA21,VB21]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14), op15(a._15,b._15), op16(a._16,b._16), op17(a._17,b._17), op18(a._18,b._18), op19(a._19,b._19), op20(a._20,b._20), op21(a._21,b._21)); } implicit def OpTuple21Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], op15 : BinaryOp[VA15,VS,O,RV15], op16 : BinaryOp[VA16,VS,O,RV16], op17 : BinaryOp[VA17,VS,O,RV17], op18 : BinaryOp[VA18,VS,O,RV18], op19 : BinaryOp[VA19,VS,O,RV19], op20 : BinaryOp[VA20,VS,O,RV20], op21 : BinaryOp[VA21,VS,O,RV21], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s), op15(a._15,s), op16(a._16,s), op17(a._17,s), op18(a._18,s), op19(a._19,s), op20(a._20,s), op21(a._21,s)); } implicit def OpScalarTuple21[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], op15 : BinaryOp[VS,VB15,O,RV15], op16 : BinaryOp[VS,VB16,O,RV16], op17 : BinaryOp[VS,VB17,O,RV17], op18 : BinaryOp[VS,VB18,O,RV18], op19 : BinaryOp[VS,VB19,O,RV19], op20 : BinaryOp[VS,VB20,O,RV20], op21 : BinaryOp[VS,VB21,O,RV21], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14), op15(s,b._15), op16(s,b._16), op17(s,b._17), op18(s,b._18), op19(s,b._19), op20(s,b._20), op21(s,b._21)); } implicit def OpTuple22Tuple22[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,VB22,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22,O<:OpType] (implicit op1 : BinaryOp[VA1,VB1,O,RV1], op2 : BinaryOp[VA2,VB2,O,RV2], op3 : BinaryOp[VA3,VB3,O,RV3], op4 : BinaryOp[VA4,VB4,O,RV4], op5 : BinaryOp[VA5,VB5,O,RV5], op6 : BinaryOp[VA6,VB6,O,RV6], op7 : BinaryOp[VA7,VB7,O,RV7], op8 : BinaryOp[VA8,VB8,O,RV8], op9 : BinaryOp[VA9,VB9,O,RV9], op10 : BinaryOp[VA10,VB10,O,RV10], op11 : BinaryOp[VA11,VB11,O,RV11], op12 : BinaryOp[VA12,VB12,O,RV12], op13 : BinaryOp[VA13,VB13,O,RV13], op14 : BinaryOp[VA14,VB14,O,RV14], op15 : BinaryOp[VA15,VB15,O,RV15], op16 : BinaryOp[VA16,VB16,O,RV16], op17 : BinaryOp[VA17,VB17,O,RV17], op18 : BinaryOp[VA18,VB18,O,RV18], op19 : BinaryOp[VA19,VB19,O,RV19], op20 : BinaryOp[VA20,VB20,O,RV20], op21 : BinaryOp[VA21,VB21,O,RV21], op22 : BinaryOp[VA22,VB22,O,RV22], c1 : CompatibleShape[VA1,VB1], c2 : CompatibleShape[VA2,VB2], c3 : CompatibleShape[VA3,VB3], c4 : CompatibleShape[VA4,VB4], c5 : CompatibleShape[VA5,VB5], c6 : CompatibleShape[VA6,VB6], c7 : CompatibleShape[VA7,VB7], c8 : CompatibleShape[VA8,VB8], c9 : CompatibleShape[VA9,VB9], c10 : CompatibleShape[VA10,VB10], c11 : CompatibleShape[VA11,VB11], c12 : CompatibleShape[VA12,VB12], c13 : CompatibleShape[VA13,VB13], c14 : CompatibleShape[VA14,VB14], c15 : CompatibleShape[VA15,VB15], c16 : CompatibleShape[VA16,VB16], c17 : CompatibleShape[VA17,VB17], c18 : CompatibleShape[VA18,VB18], c19 : CompatibleShape[VA19,VB19], c20 : CompatibleShape[VA20,VB20], c21 : CompatibleShape[VA21,VB21], c22 : CompatibleShape[VA22,VB22]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,VB22),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22),(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,VB22),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22), b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,VB22)) = (op1(a._1,b._1), op2(a._2,b._2), op3(a._3,b._3), op4(a._4,b._4), op5(a._5,b._5), op6(a._6,b._6), op7(a._7,b._7), op8(a._8,b._8), op9(a._9,b._9), op10(a._10,b._10), op11(a._11,b._11), op12(a._12,b._12), op13(a._13,b._13), op14(a._14,b._14), op15(a._15,b._15), op16(a._16,b._16), op17(a._17,b._17), op18(a._18,b._18), op19(a._19,b._19), op20(a._20,b._20), op21(a._21,b._21), op22(a._22,b._22)); } implicit def OpTuple22Scalar[VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22,VS,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22,O<:OpType] (implicit op1 : BinaryOp[VA1,VS,O,RV1], op2 : BinaryOp[VA2,VS,O,RV2], op3 : BinaryOp[VA3,VS,O,RV3], op4 : BinaryOp[VA4,VS,O,RV4], op5 : BinaryOp[VA5,VS,O,RV5], op6 : BinaryOp[VA6,VS,O,RV6], op7 : BinaryOp[VA7,VS,O,RV7], op8 : BinaryOp[VA8,VS,O,RV8], op9 : BinaryOp[VA9,VS,O,RV9], op10 : BinaryOp[VA10,VS,O,RV10], op11 : BinaryOp[VA11,VS,O,RV11], op12 : BinaryOp[VA12,VS,O,RV12], op13 : BinaryOp[VA13,VS,O,RV13], op14 : BinaryOp[VA14,VS,O,RV14], op15 : BinaryOp[VA15,VS,O,RV15], op16 : BinaryOp[VA16,VS,O,RV16], op17 : BinaryOp[VA17,VS,O,RV17], op18 : BinaryOp[VA18,VS,O,RV18], op19 : BinaryOp[VA19,VS,O,RV19], op20 : BinaryOp[VA20,VS,O,RV20], op21 : BinaryOp[VA21,VS,O,RV21], op22 : BinaryOp[VA22,VS,O,RV22], s : Scalar[VS]) : BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22)] = new BinaryOp[(VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22),VS,O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22)] { def opType = op1.opType; def apply(a : (VA1,VA2,VA3,VA4,VA5,VA6,VA7,VA8,VA9,VA10,VA11,VA12,VA13,VA14,VA15,VA16,VA17,VA18,VA19,VA20,VA21,VA22), s : VS) = (op1(a._1,s), op2(a._2,s), op3(a._3,s), op4(a._4,s), op5(a._5,s), op6(a._6,s), op7(a._7,s), op8(a._8,s), op9(a._9,s), op10(a._10,s), op11(a._11,s), op12(a._12,s), op13(a._13,s), op14(a._14,s), op15(a._15,s), op16(a._16,s), op17(a._17,s), op18(a._18,s), op19(a._19,s), op20(a._20,s), op21(a._21,s), op22(a._22,s)); } implicit def OpScalarTuple22[VS,VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,VB22,RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22,O<:OpType] (implicit op1 : BinaryOp[VS,VB1,O,RV1], op2 : BinaryOp[VS,VB2,O,RV2], op3 : BinaryOp[VS,VB3,O,RV3], op4 : BinaryOp[VS,VB4,O,RV4], op5 : BinaryOp[VS,VB5,O,RV5], op6 : BinaryOp[VS,VB6,O,RV6], op7 : BinaryOp[VS,VB7,O,RV7], op8 : BinaryOp[VS,VB8,O,RV8], op9 : BinaryOp[VS,VB9,O,RV9], op10 : BinaryOp[VS,VB10,O,RV10], op11 : BinaryOp[VS,VB11,O,RV11], op12 : BinaryOp[VS,VB12,O,RV12], op13 : BinaryOp[VS,VB13,O,RV13], op14 : BinaryOp[VS,VB14,O,RV14], op15 : BinaryOp[VS,VB15,O,RV15], op16 : BinaryOp[VS,VB16,O,RV16], op17 : BinaryOp[VS,VB17,O,RV17], op18 : BinaryOp[VS,VB18,O,RV18], op19 : BinaryOp[VS,VB19,O,RV19], op20 : BinaryOp[VS,VB20,O,RV20], op21 : BinaryOp[VS,VB21,O,RV21], op22 : BinaryOp[VS,VB22,O,RV22], s : Scalar[VS]) : BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,VB22),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22)] = new BinaryOp[VS,(VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,VB22),O,(RV1,RV2,RV3,RV4,RV5,RV6,RV7,RV8,RV9,RV10,RV11,RV12,RV13,RV14,RV15,RV16,RV17,RV18,RV19,RV20,RV21,RV22)] { def opType = op1.opType; def apply(s : VS, b : (VB1,VB2,VB3,VB4,VB5,VB6,VB7,VB8,VB9,VB10,VB11,VB12,VB13,VB14,VB15,VB16,VB17,VB18,VB19,VB20,VB21,VB22)) = (op1(s,b._1), op2(s,b._2), op3(s,b._3), op4(s,b._4), op5(s,b._5), op6(s,b._6), op7(s,b._7), op8(s,b._8), op9(s,b._9), op10(s,b._10), op11(s,b._11), op12(s,b._12), op13(s,b._13), op14(s,b._14), op15(s,b._15), op16(s,b._16), op17(s,b._17), op18(s,b._18), op19(s,b._19), op20(s,b._20), op21(s,b._21), op22(s,b._22)); } } object RichTuples { class RichTuple2[@specialized V1, @specialized V2](override val repr : (V1,V2)) extends MutableNumericOps[(V1,V2)]; class RichTuple3[@specialized V1, @specialized V2, @specialized V3](override val repr : (V1,V2,V3)) extends MutableNumericOps[(V1,V2,V3)]; class RichTuple4[V1, V2, V3, V4](override val repr : (V1,V2,V3,V4)) extends MutableNumericOps[(V1,V2,V3,V4)]; class RichTuple5[V1, V2, V3, V4, V5](override val repr : (V1,V2,V3,V4,V5)) extends MutableNumericOps[(V1,V2,V3,V4,V5)]; class RichTuple6[V1, V2, V3, V4, V5, V6](override val repr : (V1,V2,V3,V4,V5,V6)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6)]; class RichTuple7[V1, V2, V3, V4, V5, V6, V7](override val repr : (V1,V2,V3,V4,V5,V6,V7)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7)]; class RichTuple8[V1, V2, V3, V4, V5, V6, V7, V8](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8)]; class RichTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9)]; class RichTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10)]; class RichTuple11[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11)]; class RichTuple12[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12)]; class RichTuple13[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13)]; class RichTuple14[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14)]; class RichTuple15[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15)]; class RichTuple16[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16)]; class RichTuple17[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17)]; class RichTuple18[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18)]; class RichTuple19[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19)]; class RichTuple20[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20)]; class RichTuple21[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20,V21)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20,V21)]; class RichTuple22[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22](override val repr : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20,V21,V22)) extends MutableNumericOps[(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20,V21,V22)]; } trait RichTupleImplicits { import RichTuples._; implicit def richTuple2[@specialized V1, @specialized V2](value : (V1,V2)) = new RichTuple2(value); implicit def richTuple3[@specialized V1, @specialized V2, @specialized V3](value : (V1,V2,V3)) = new RichTuple3(value); implicit def richTuple4[V1, V2, V3, V4](value : (V1,V2,V3,V4)) = new RichTuple4(value); implicit def richTuple5[V1, V2, V3, V4, V5](value : (V1,V2,V3,V4,V5)) = new RichTuple5(value); implicit def richTuple6[V1, V2, V3, V4, V5, V6](value : (V1,V2,V3,V4,V5,V6)) = new RichTuple6(value); implicit def richTuple7[V1, V2, V3, V4, V5, V6, V7](value : (V1,V2,V3,V4,V5,V6,V7)) = new RichTuple7(value); implicit def richTuple8[V1, V2, V3, V4, V5, V6, V7, V8](value : (V1,V2,V3,V4,V5,V6,V7,V8)) = new RichTuple8(value); implicit def richTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9)) = new RichTuple9(value); implicit def richTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10)) = new RichTuple10(value); implicit def richTuple11[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11)) = new RichTuple11(value); implicit def richTuple12[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12)) = new RichTuple12(value); implicit def richTuple13[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13)) = new RichTuple13(value); implicit def richTuple14[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14)) = new RichTuple14(value); implicit def richTuple15[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15)) = new RichTuple15(value); implicit def richTuple16[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16)) = new RichTuple16(value); implicit def richTuple17[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17)) = new RichTuple17(value); implicit def richTuple18[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18)) = new RichTuple18(value); implicit def richTuple19[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19)) = new RichTuple19(value); implicit def richTuple20[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20)) = new RichTuple20(value); implicit def richTuple21[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20,V21)) = new RichTuple21(value); implicit def richTuple22[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22](value : (V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V20,V21,V22)) = new RichTuple22(value); } ================================================ FILE: src/main/scala/scalala/operators/UnaryOp.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import scala.annotation.implicitNotFound; import scala.collection.generic.CanBuildFrom; /** * Operation of type O that returns That from arguments A and B. * * @author dramage */ @implicitNotFound(msg="Could not find a way to ${O} value of type ${This}") trait UnaryOp[@specialized -This, O<:OpType, +That] { // should not inherit from This=>That because the compiler will try to use it as a conversion. def opType : O; def apply(t: This):That } object UnaryOp extends UnaryTupleOps { // // Negation // implicit object OpNegI extends UnaryOp[Int,OpNeg,Int] { def opType = OpNeg; def apply(v : Int) = -v; } implicit object OpNegS extends UnaryOp[Short,OpNeg,Short] { def opType = OpNeg; def apply(v : Short) = (-v).asInstanceOf[Short]; } implicit object OpNegL extends UnaryOp[Long,OpNeg,Long] { def opType = OpNeg; def apply(v : Long) = -v; } implicit object OpNegF extends UnaryOp[Float,OpNeg,Float] { def opType = OpNeg; def apply(v : Float) = -v; } implicit object OpNegD extends UnaryOp[Double,OpNeg,Double] { def opType = OpNeg; def apply(v : Double) = -v; } // // Not // implicit object OpNotB extends UnaryOp[Boolean,OpNot,Boolean] { def opType = OpNot; def apply(v : Boolean) = !v; } // // Maps // implicit def OpMap[K,V,RV,O<:OpType,M,That] (implicit view : M=>scala.collection.Map[K,V], op : UnaryOp[V,O,RV], bf : CanBuildFrom[M,(K,RV),That]) : UnaryOp[M, O, That] = new UnaryOp[M, O, That] { def opType = op.opType; def apply(m : M) = { val builder = bf(m); for ((k,v) <- m) { builder += k -> op(v); } builder.result; } } // // Seqs // implicit def OpSeq[V,RV,O<:OpType,S,That] (implicit view : S=>scala.collection.Seq[V], op : UnaryOp[V,O,RV], bf : CanBuildFrom[S,RV,That]) : UnaryOp[S,O,That] = new UnaryOp[S,O,That] { def opType = op.opType; def apply(s : S) = { val builder = bf(s); for (v <- s) { builder += op(v); } builder.result; } } // // Arrays // implicit def OpArray[V,RV,O<:OpType] (implicit op : UnaryOp[V,O,RV], mf : Manifest[RV]) : UnaryOp[Array[V],O,Array[RV]] = new UnaryOp[Array[V],O,Array[RV]] { def opType = op.opType; def apply(a : Array[V]) = { var rv = new Array[RV](a.length); var i = 0; while (i < rv.length) { rv(i) = op(a(i)); i += 1; } rv; } } } ================================================ FILE: src/main/scala/scalala/operators/ValuesMonadic.scala ================================================ package scalala.operators import scalala.generic.collection.CanMapValues /** * * Represents objects that can have their values mapped. * @author dlwh */ trait ValuesMonadic[+This,V] { def repr: This; def map[TT>:This,O,That](fn : V => O) (implicit bf : CanMapValues[TT, V, O, That]) : That = bf.map(repr,fn); } trait HasValuesMonadic[+This,V] { def values: ValuesMonadic[This,V]; } object HasValuesMonadic { implicit def arrayHasValues[V](arr: Array[V]): HasValuesMonadic[Array[V], V] = new HasValuesMonadic[Array[V],V] { def values = new ValuesMonadic[Array[V],V] { def repr = arr; } } } ================================================ FILE: src/main/scala/scalala/operators/bundles/VectorSpace.scala ================================================ package scalala package operators package bundles import scalar.Scalar import generic.math.CanNorm import generic.collection.{CanZipMapValues, CanCopy, CanMapValues, CanCreateZerosLike} /** * A VectorSpace has vectors S with vector addition and multiplication * by scalars, along with a privileged zero vector. * We add in implicits for operations that fall out of them. * @author dlwh */ trait VectorSpace[S,V] { implicit def field : Scalar[S] implicit def numericOps(t: V):NumericOps[V]; implicit def hasValuesMonadic(t: V):HasValuesMonadic[V,S] implicit def mapValues: CanMapValues[V,S,S,V] implicit def zipMapValues: CanZipMapValues[V,S,S,V] implicit val zeros: CanCreateZerosLike[V, V]; def ones(v: V) = zeros(v) + field.one; // implicit def negV : UnaryOp[V,OpNeg,V]; implicit def addSV : BinaryOp[S,V,OpAdd,V]; implicit def addVS : BinaryOp[V,S,OpAdd,V]; implicit def addVV : BinaryOp[V,V,OpAdd,V]; implicit def subSV : BinaryOp[S,V,OpSub,V]; implicit def subVS : BinaryOp[V,S,OpSub,V]; implicit def subVV : BinaryOp[V,V,OpSub,V]; implicit def mulSV : BinaryOp[S,V,OpMul,V]; implicit def mulVS : BinaryOp[V,S,OpMul,V]; implicit def mulVV : BinaryOp[V,V,OpMul,V]; implicit def divSV : BinaryOp[S,V,OpDiv,V]; implicit def divVS : BinaryOp[V,S,OpDiv,V]; implicit def divVV : BinaryOp[V,V,OpDiv,V]; } /** * Adds in mutating operations * @author dlwh */ trait MutableVectorSpace[S,V] extends VectorSpace[S,V] { override implicit def numericOps(t: V):MutableNumericOps[V] implicit val copy: CanCopy[V]; implicit def addIntoVS : BinaryUpdateOp[V,S,OpAdd]; implicit def addIntoVV : BinaryUpdateOp[V,V,OpAdd]; implicit def subIntoVS : BinaryUpdateOp[V,S,OpSub]; implicit def subIntoVV : BinaryUpdateOp[V,V,OpSub]; implicit def divIntoVS : BinaryUpdateOp[V,S,OpDiv]; implicit def divIntoVV : BinaryUpdateOp[V,V,OpDiv]; implicit def mulIntoVS : BinaryUpdateOp[V,S,OpMul]; implicit def mulIntoVV : BinaryUpdateOp[V,V,OpMul]; } object VectorSpace { implicit def make[V,S](implicit _field : Scalar[S], _numericOps: V=>NumericOps[V], _hasValuesMonadic: V=>HasValuesMonadic[V,S], _mapValues: CanMapValues[V,S,S,V], _zipMapValues: CanZipMapValues[V,S,S,V], _zeros: CanCreateZerosLike[V, V], // _negV : UnaryOp[V,OpNeg,V], _addSV : BinaryOp[S,V,OpAdd,V], _addVS : BinaryOp[V,S,OpAdd,V], _addVV : BinaryOp[V,V,OpAdd,V], _subSV : BinaryOp[S,V,OpSub,V], _subVS : BinaryOp[V,S,OpSub,V], _subVV : BinaryOp[V,V,OpSub,V], _mulSV : BinaryOp[S,V,OpMul,V], _mulVS : BinaryOp[V,S,OpMul,V], _mulVV : BinaryOp[V,V,OpMul,V], _divSV : BinaryOp[S,V,OpDiv,V], _divVS : BinaryOp[V,S,OpDiv,V], _divVV : BinaryOp[V,V,OpDiv,V]):VectorSpace[S,V] = { new VectorSpace[S,V] { def field : Scalar[S] = _field; def numericOps(t: V):NumericOps[V] = _numericOps(t) def hasValuesMonadic(t: V):HasValuesMonadic[V,S] = _hasValuesMonadic(t) def mapValues: CanMapValues[V,S,S,V] = _mapValues; def zipMapValues: CanZipMapValues[V,S,S,V] = _zipMapValues; implicit val zeros: CanCreateZerosLike[V, V] = _zeros // implicit def negV : UnaryOp[V,OpNeg,V] = _negV; implicit def addSV : BinaryOp[S,V,OpAdd,V] = _addSV; implicit def addVS : BinaryOp[V,S,OpAdd,V] = _addVS; implicit def addVV : BinaryOp[V,V,OpAdd,V] = _addVV; implicit def subSV : BinaryOp[S,V,OpSub,V] = _subSV; implicit def subVS : BinaryOp[V,S,OpSub,V] = _subVS; implicit def subVV : BinaryOp[V,V,OpSub,V] = _subVV; implicit def mulSV : BinaryOp[S,V,OpMul,V] = _mulSV; implicit def mulVS : BinaryOp[V,S,OpMul,V] = _mulVS; implicit def mulVV : BinaryOp[V,V,OpMul,V] = _mulVV; implicit def divSV : BinaryOp[S,V,OpDiv,V] = _divSV; implicit def divVS : BinaryOp[V,S,OpDiv,V] = _divVS; implicit def divVV : BinaryOp[V,V,OpDiv,V] = _divVV; } } } object MutableVectorSpace { implicit def make[V,S](implicit _field : Scalar[S], _numericOps: V=>MutableNumericOps[V], _hasValuesMonadic: V=>HasValuesMonadic[V,S], _mapValues: CanMapValues[V,S,S,V], _zipMapValues: CanZipMapValues[V,S,S,V], _zeros: CanCreateZerosLike[V, V], _copy: CanCopy[V], // _negV : UnaryOp[V,OpNeg,V], _addSV : BinaryOp[S,V,OpAdd,V], _addVS : BinaryOp[V,S,OpAdd,V], _addVV : BinaryOp[V,V,OpAdd,V], _subSV : BinaryOp[S,V,OpSub,V], _subVS : BinaryOp[V,S,OpSub,V], _subVV : BinaryOp[V,V,OpSub,V], _mulSV : BinaryOp[S,V,OpMul,V], _mulVS : BinaryOp[V,S,OpMul,V], _mulVV : BinaryOp[V,V,OpMul,V], _divSV : BinaryOp[S,V,OpDiv,V], _divVS : BinaryOp[V,S,OpDiv,V], _divVV : BinaryOp[V,V,OpDiv,V], _addIntoVS : BinaryUpdateOp[V,S,OpAdd], _addIntoVV : BinaryUpdateOp[V,V,OpAdd], _mulIntoVS : BinaryUpdateOp[V,S,OpMul], _mulIntoVV : BinaryUpdateOp[V,V,OpMul], _subIntoVS : BinaryUpdateOp[V,S,OpSub], _subIntoVV : BinaryUpdateOp[V,V,OpSub], _divIntoVS : BinaryUpdateOp[V,S,OpDiv], _divIntoVV : BinaryUpdateOp[V,V,OpDiv]):MutableVectorSpace[S,V] = { new MutableVectorSpace[S,V] { def field : Scalar[S] = _field; def numericOps(t: V) = _numericOps(t) def hasValuesMonadic(t: V):HasValuesMonadic[V,S] = _hasValuesMonadic(t) def mapValues: CanMapValues[V,S,S,V] = _mapValues; def zipMapValues: CanZipMapValues[V,S,S,V] = _zipMapValues; implicit val zeros: CanCreateZerosLike[V, V] = _zeros implicit val copy: CanCopy[V] = _copy; // implicit def negV : UnaryOp[V,OpNeg,V] = _negV; implicit def addSV : BinaryOp[S,V,OpAdd,V] = _addSV; implicit def addVS : BinaryOp[V,S,OpAdd,V] = _addVS; implicit def addVV : BinaryOp[V,V,OpAdd,V] = _addVV; implicit def subSV : BinaryOp[S,V,OpSub,V] = _subSV; implicit def subVS : BinaryOp[V,S,OpSub,V] = _subVS; implicit def subVV : BinaryOp[V,V,OpSub,V] = _subVV; implicit def mulSV : BinaryOp[S,V,OpMul,V] = _mulSV; implicit def mulVS : BinaryOp[V,S,OpMul,V] = _mulVS; implicit def mulVV : BinaryOp[V,V,OpMul,V] = _mulVV; implicit def divSV : BinaryOp[S,V,OpDiv,V] = _divSV; implicit def divVS : BinaryOp[V,S,OpDiv,V] = _divVS; implicit def divVV : BinaryOp[V,V,OpDiv,V] = _divVV; implicit def divIntoVV = _divIntoVV implicit def divIntoVS = _divIntoVS implicit def subIntoVV = _subIntoVV implicit def subIntoVS = _subIntoVS implicit def addIntoVV = _addIntoVV implicit def addIntoVS = _addIntoVS implicit def mulIntoVV = _mulIntoVV implicit def mulIntoVS = _mulIntoVS } } } /** * VectorSpace with an innerproduct * @author dlwh */ trait InnerProductSpace[S,V] extends VectorSpace[S,V] { implicit def innerVV : BinaryOp[V,V,OpMulInner,S]; } object InnerProductSpace { implicit def make[V,S](implicit _field : Scalar[S], _numericOps: V=>NumericOps[V], _hasValuesMonadic: V=>HasValuesMonadic[V,S], _mapValues: CanMapValues[V,S,S,V], _zipMapValues: CanZipMapValues[V,S,S,V], _zeros: CanCreateZerosLike[V, V], // _negV : UnaryOp[V,OpNeg,V], _addSV : BinaryOp[S,V,OpAdd,V], _addVS : BinaryOp[V,S,OpAdd,V], _addVV : BinaryOp[V,V,OpAdd,V], _subSV : BinaryOp[S,V,OpSub,V], _subVS : BinaryOp[V,S,OpSub,V], _subVV : BinaryOp[V,V,OpSub,V], _mulSV : BinaryOp[S,V,OpMul,V], _mulVS : BinaryOp[V,S,OpMul,V], _mulVV : BinaryOp[V,V,OpMul,V], _divSV : BinaryOp[S,V,OpDiv,V], _divVS : BinaryOp[V,S,OpDiv,V], _divVV : BinaryOp[V,V,OpDiv,V], _innerVV : BinaryOp[V,V,OpMulInner,S]):InnerProductSpace[S,V] = { new InnerProductSpace[S,V] { def field : Scalar[S] = _field; def numericOps(t: V):NumericOps[V] = _numericOps(t) def hasValuesMonadic(t: V):HasValuesMonadic[V,S] = _hasValuesMonadic(t) def mapValues: CanMapValues[V,S,S,V] = _mapValues; def zipMapValues: CanZipMapValues[V,S,S,V] = _zipMapValues; implicit val zeros: CanCreateZerosLike[V, V] = _zeros // implicit def negV : UnaryOp[V,OpNeg,V] = _negV; implicit def addSV : BinaryOp[S,V,OpAdd,V] = _addSV; implicit def addVS : BinaryOp[V,S,OpAdd,V] = _addVS; implicit def addVV : BinaryOp[V,V,OpAdd,V] = _addVV; implicit def subSV : BinaryOp[S,V,OpSub,V] = _subSV; implicit def subVS : BinaryOp[V,S,OpSub,V] = _subVS; implicit def subVV : BinaryOp[V,V,OpSub,V] = _subVV; implicit def mulSV : BinaryOp[S,V,OpMul,V] = _mulSV; implicit def mulVS : BinaryOp[V,S,OpMul,V] = _mulVS; implicit def mulVV : BinaryOp[V,V,OpMul,V] = _mulVV; implicit def divSV : BinaryOp[S,V,OpDiv,V] = _divSV; implicit def divVS : BinaryOp[V,S,OpDiv,V] = _divVS; implicit def divVV : BinaryOp[V,V,OpDiv,V] = _divVV; implicit def innerVV : BinaryOp[V,V,OpMulInner,S] = _innerVV; } } } trait MutableInnerProductSpace[S,V] extends InnerProductSpace[S,V] with MutableVectorSpace[S,V]; object MutableInnerProductSpace { implicit def make[S,V](implicit _field : Scalar[S], _numericOps: V=>MutableNumericOps[V], _hasValuesMonadic: V=>HasValuesMonadic[V,S], _mapValues: CanMapValues[V,S,S,V], _zipMapValues: CanZipMapValues[V,S,S,V], _zeros: CanCreateZerosLike[V, V], _copy: CanCopy[V], // _negV : UnaryOp[V,OpNeg,V], _addSV : BinaryOp[S,V,OpAdd,V], _addVS : BinaryOp[V,S,OpAdd,V], _addVV : BinaryOp[V,V,OpAdd,V], _subSV : BinaryOp[S,V,OpSub,V], _subVS : BinaryOp[V,S,OpSub,V], _subVV : BinaryOp[V,V,OpSub,V], _mulSV : BinaryOp[S,V,OpMul,V], _mulVS : BinaryOp[V,S,OpMul,V], _mulVV : BinaryOp[V,V,OpMul,V], _divSV : BinaryOp[S,V,OpDiv,V], _divVS : BinaryOp[V,S,OpDiv,V], _divVV : BinaryOp[V,V,OpDiv,V], _addIntoVS : BinaryUpdateOp[V,S,OpAdd], _addIntoVV : BinaryUpdateOp[V,V,OpAdd], _mulIntoVS : BinaryUpdateOp[V,S,OpMul], _mulIntoVV : BinaryUpdateOp[V,V,OpMul], _subIntoVS : BinaryUpdateOp[V,S,OpSub], _subIntoVV : BinaryUpdateOp[V,V,OpSub], _divIntoVS : BinaryUpdateOp[V,S,OpDiv], _divIntoVV : BinaryUpdateOp[V,V,OpDiv], _innerVV : BinaryOp[V,V,OpMulInner,S]):MutableInnerProductSpace[S,V] = { new MutableInnerProductSpace[S,V] { def field : Scalar[S] = _field; def numericOps(t: V) = _numericOps(t) def hasValuesMonadic(t: V):HasValuesMonadic[V,S] = _hasValuesMonadic(t) def mapValues: CanMapValues[V,S,S,V] = _mapValues; def zipMapValues: CanZipMapValues[V,S,S,V] = _zipMapValues; implicit val zeros: CanCreateZerosLike[V, V] = _zeros implicit val copy: CanCopy[V] = _copy; // implicit def negV : UnaryOp[V,OpNeg,V] = _negV; implicit def addSV : BinaryOp[S,V,OpAdd,V] = _addSV; implicit def addVS : BinaryOp[V,S,OpAdd,V] = _addVS; implicit def addVV : BinaryOp[V,V,OpAdd,V] = _addVV; implicit def subSV : BinaryOp[S,V,OpSub,V] = _subSV; implicit def subVS : BinaryOp[V,S,OpSub,V] = _subVS; implicit def subVV : BinaryOp[V,V,OpSub,V] = _subVV; implicit def mulSV : BinaryOp[S,V,OpMul,V] = _mulSV; implicit def mulVS : BinaryOp[V,S,OpMul,V] = _mulVS; implicit def mulVV : BinaryOp[V,V,OpMul,V] = _mulVV; implicit def divSV : BinaryOp[S,V,OpDiv,V] = _divSV; implicit def divVS : BinaryOp[V,S,OpDiv,V] = _divVS; implicit def divVV : BinaryOp[V,V,OpDiv,V] = _divVV; implicit def innerVV : BinaryOp[V,V,OpMulInner,S] = _innerVV; implicit def divIntoVV = _divIntoVV implicit def divIntoVS = _divIntoVS implicit def subIntoVV = _subIntoVV implicit def subIntoVS = _subIntoVS implicit def addIntoVV = _addIntoVV implicit def addIntoVS = _addIntoVS implicit def mulIntoVV = _mulIntoVV implicit def mulIntoVS = _mulIntoVS } } } ================================================ FILE: src/main/scala/scalala/operators/codegen/BinaryOpGenerator.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; package codegen; import scala.annotation.implicitNotFound; import scala.collection.mutable.HashMap; import scalala.scalar.Scalar; trait Generator { protected def shorten(m : Manifest[_]) = m.toString.replaceAll(".*(\\$|\\.)","").replaceAll("\\[|\\]",""); protected def toImport(m : Manifest[_]) = if (m.erasure.getName.contains(".")) "import "+m.erasure.getName else ""; def mkInnerCode : String; } abstract class Function2Generator[A,B,To] (implicit ma : Manifest[A], mb : Manifest[B], mt : Manifest[To]) extends Generator { self => def className : String; def mkClassCode : String = { """ | %s | %s | %s | class %s extends ((%s,%s)=>%s) { | override def apply(a : %s, b : %s) : %s = { %s | } | override def toString = "DynamicallyCompiled"+getClass.getName | } """.stripMargin.format( toImport(ma), toImport(mb), toImport(mt), className, ma, mb, mt, ma, mb, mt, mkInnerCode.replaceAll("\\$a","a").replaceAll("\\$b","b") ); } def prefix(code : String) : Function2Generator[A,B,To] = { new Function2Generator[A,B,To] { override def className = "Prefixed"+self.className override def mkInnerCode = code + self.mkInnerCode } } def getInstance = DynamicCompiler.define(className,mkClassCode).newInstance().asInstanceOf[((A,B)=>To)]; } abstract class JoinGenerator[A,B,To] (implicit ma : Manifest[A], mb : Manifest[B], mt : Manifest[To]) extends Function2Generator[A,B,To]; class JoinArrayArrayGenerator[A,B,To](override val className : String) (init : String, loop : Function2Generator[A,B,_], done : String) (implicit ma : Manifest[A], mb : Manifest[B], mt : Manifest[To]) extends JoinGenerator[Array[A],Array[B],To] { def mkInnerCode : String = { """ require($a.length == $b.length) %s var i = 0; while (i < $a.length) { { %s } i += 1; } %s """.format( init, loop.mkInnerCode.replaceAll("\\$a","\\$a(i)").replaceAll("\\$b","\\$b(i)"), done ) } } /** * Generates inlined, specialized code for BinaryOp[A,B,O,To]. */ abstract class BinaryOpGenerator[A,B,O<:OpType,To]( implicit ma : Manifest[A], mb : Manifest[B], mo : Manifest[O], mt : Manifest[To]) extends Function2Generator[A,B,To] { def className() = shorten(mo)+shorten(ma)+shorten(mb); override def mkClassCode : String = { """ | import scalala.operators._ | class %s extends BinaryOp[%s,%s,%s,%s] { | override def opType = %s | override def apply(a : %s, b : %s) : %s = { %s | } | override def toString = "DynamicallyCompiled"+getClass.getName | } """.stripMargin.format( className, ma, mb, shorten(mo), mt, shorten(mo), ma, mb, mt, mkInnerCode.replaceAll("\\$a","a").replaceAll("\\$b","b") ); } override def getInstance = super.getInstance.asInstanceOf[BinaryOp[A,B,O,To]]; } object BinaryOpGenerator { class BinaryOpScalarScalarInfixGenerator[V1,V2,O<:OpType,RV](val opType : O, symbol : Char) (implicit s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) extends BinaryOpGenerator[V1,V2,O,RV] { def mkInnerCode = "$a"+symbol+"$b" } implicit def BinaryOpAddScalarScalarGenerator[V1,V2,RV] (implicit s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mr : Manifest[RV]) : BinaryOpGenerator[V1,V2,OpAdd,RV] = new BinaryOpScalarScalarInfixGenerator(OpAdd,'+'); implicit def BinaryOpSubScalarScalarGenerator[V1,V2,RV] (implicit s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mr : Manifest[RV]) : BinaryOpGenerator[V1,V2,OpSub,RV] = new BinaryOpScalarScalarInfixGenerator(OpSub,'-'); implicit def BinaryOpMulScalarScalarGenerator[V1,V2,RV] (implicit s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mr : Manifest[RV]) : BinaryOpGenerator[V1,V2,OpMul,RV] = new BinaryOpScalarScalarInfixGenerator(OpMul,'*'); implicit def BinaryOpDivScalarScalarGenerator[V1,V2,RV] (implicit s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mr : Manifest[RV]) : BinaryOpGenerator[V1,V2,OpDiv,RV] = new BinaryOpScalarScalarInfixGenerator(OpDiv,'/'); implicit def BinaryOpArrayArrayGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[Array[V1],Array[V2],O,Array[RV]] = new BinaryOpGenerator[Array[V1],Array[V2],O,Array[RV]] { def mkInnerCode = """ require($a.length == $b.length, "Inputs must be the same length"); var rv = new Array[%s]($a.length); var i = 0; while (i < rv.length) { rv(i) = %s; i += 1; } rv; """.format(mr.toString, op.mkInnerCode.replaceAll("\\$a","\\$a(i)").replaceAll("\\$b","\\$b(i)")); } implicit def BinaryOpArrayScalarGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], s : Scalar[V2], mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[Array[V1], V2, O, Array[RV]] = new BinaryOpGenerator[Array[V1], V2, O, Array[RV]] { def mkInnerCode = """ var rv = new Array[%s]($a.length); var i = 0; while (i < rv.length) { rv(i) = %s; i += 1; } rv; """.format(mr.toString, op.mkInnerCode.replaceAll("\\$a","\\$a(i)")) } implicit def BinaryOpScalarArrayGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], s : Scalar[V1], mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[V1, Array[V2], O, Array[RV]] = new BinaryOpGenerator[V1, Array[V2], O, Array[RV]] { def mkInnerCode = """ var rv = new Array[%s]($b.length); var i = 0; while (i < rv.length) { rv(i) = %s; i += 1; } rv; """.format(mr.toString, op.mkInnerCode.replaceAll("\\$b","\\$b(i)")) } import scalala.tensor.dense._; // class JoinDenseVectorDenseVectorGenerator[DV[V]<:DenseVector[V],V1,V2,RV] // (className : String, setup : code : class BinaryOpDenseVectorDenseVectorGenerator[DV[V]<:DenseVector[V],V1,V2,O<:OpType,RV] (className : String)(implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[DV[V1]], mv2 : Manifest[DV[V2]], mo : Manifest[O], mr : Manifest[DV[RV]]) extends BinaryOpGenerator[DV[V1],DV[V2],O,DV[RV]] { def mkInnerCode = """ require($a.length == $b.length, "Vectors must have the same length"); val rv = new Array[%s]($a.length); var ia = $a.offset; var ib = $b.offset; var ir = 0; while (ir < rv.length) { rv(ir) = %s; ia += $a.stride; ib += $b.stride; ir += 1; } new %s(rv); """.format(sr.manifest.toString, op.mkInnerCode.replaceAll("\\$a","\\$a.data(ia)").replaceAll("\\$b","\\$b.data(ib)"), className) } implicit def BinaryOpDenseVectorColDenseVectorColGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[DenseVectorCol[V1],DenseVectorCol[V2],O,DenseVectorCol[RV]] = new BinaryOpDenseVectorDenseVectorGenerator[DenseVectorCol,V1,V2,O,RV]( classOf[DenseVectorCol[_]].getName) implicit def BinaryOpDenseVectorRowDenseVectorRowGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[DenseVectorRow[V1],DenseVectorRow[V2],O,DenseVectorRow[RV]] = new BinaryOpDenseVectorDenseVectorGenerator[DenseVectorRow,V1,V2,O,RV]( classOf[DenseVectorRow[_]].getName) class BinaryOpDenseVectorScalarGenerator[DV[V]<:DenseVector[V],V1,V2,O<:OpType,RV] (className : String)(implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[DV[V1]], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[DV[RV]]) extends BinaryOpGenerator[DV[V1],V2,O,DV[RV]] { def mkInnerCode = """ val rv = new Array[%s]($a.length); var ia = $a.offset; var ir = 0; while (ir < rv.length) { rv(ir) = %s; ia += $a.stride; ir += 1; } new %s(rv); """.format(sr.manifest.toString, op.mkInnerCode.replaceAll("\\$a","\\$a.data(ia)"),className) } implicit def BinaryOpDenseVectorColScalarGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[DenseVectorCol[V1],V2,O,DenseVectorCol[RV]] = new BinaryOpDenseVectorScalarGenerator[DenseVectorCol,V1,V2,O,RV]( classOf[DenseVectorCol[_]].getName) implicit def BinaryOpDenseVectorRowScalarGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[DenseVectorRow[V1],V2,O,DenseVectorRow[RV]] = new BinaryOpDenseVectorScalarGenerator[DenseVectorRow,V1,V2,O,RV]( classOf[DenseVectorRow[_]].getName) class BinaryOpScalarDenseVectorGenerator[DV[V]<:DenseVector[V],V1,V2,O<:OpType,RV] (className : String)(implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[DV[V2]], mo : Manifest[O], mr : Manifest[DV[RV]]) extends BinaryOpGenerator[V1,DV[V2],O,DV[RV]] { def mkInnerCode = """ val rv = new Array[%s]($b.length); var ib = $b.offset; var ir = 0; while (ir < rv.length) { rv(ir) = %s; ib += $b.stride; ir += 1; } new %s(rv); """.format(sr.manifest.toString, op.mkInnerCode.replaceAll("\\$b","\\$b.data(ib)"),className) } implicit def BinaryOpScalarDenseVectorColGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[V1,DenseVectorCol[V2],O,DenseVectorCol[RV]] = new BinaryOpScalarDenseVectorGenerator[DenseVectorCol,V1,V2,O,RV]( classOf[DenseVectorCol[_]].getName) implicit def BinaryOpScalarDenseVectorRowGenerator[V1,V2,O<:OpType,RV] (implicit op : BinaryOpGenerator[V1,V2,O,RV], s1 : Scalar[V1], s2 : Scalar[V2], sr : Scalar[RV], c1 : V1=>RV, c2 : V2=>RV, mv1 : Manifest[V1], mv2 : Manifest[V2], mo : Manifest[O], mr : Manifest[RV]) : BinaryOpGenerator[V1,DenseVectorRow[V2],O,DenseVectorRow[RV]] = new BinaryOpScalarDenseVectorGenerator[DenseVectorRow,V1,V2,O,RV]( classOf[DenseVectorRow[_]].getName) } object GeneratedRegistryEntries { import scalala.tensor.dense._; def main(args : Array[String]) { val ops = Array("OpAdd","OpSub","OpMul","OpDiv") val scalars = Array("Int","Long","Float","Double") val tensors = Array("Array","DenseVectorRow","DenseVectorCol") // returns the scalar result of combining the two operands def sr(s1 : String, s2 : String) = if (scalars.indexOf(s1) < scalars.indexOf(s2)) s2 else s1; val opsTensorTensorSame = for (t <- tensors; s1 <- scalars; s2 <- scalars; op <- ops) yield "Registry.register[%s[%s],%s[%s],%s,%s[%s]]".format(t,s1,t,s2,op,t,sr(s1,s2)) val opsTensorScalar = for (t <- tensors; s1 <- scalars; s2 <- scalars; op <- ops) yield "Registry.register[%s[%s],%s,%s,%s[%s]]".format(t,s1,s2,op,t,sr(s1,s2)); val opsScalarTensor = for (t <- tensors; s1 <- scalars; s2 <- scalars; op <- ops) yield "Registry.register[%s,%s[%s],%s,%s[%s]]".format(s1,t,s2,op,t,sr(s1,s2)); println(""" | def init() { | initTensorTensorSame(); | initTensorScalar(); | initScalarTensor(); | } | | def initTensorTensorSame() { | %s | } | | def initTensorScalar() { | %s | } | | def initScalarTensor() { | %s | } """.stripMargin.format( opsTensorTensorSame.mkString("\n "), opsTensorScalar.mkString("\n "), opsScalarTensor.mkString("\n "))); } } ================================================ FILE: src/main/scala/scalala/operators/codegen/DynamicCompiler.scala ================================================ /* * Copyright 2010 Twitter, Inc. * * 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. */ package scalala package operators.codegen import java.io.File import java.util.jar.JarFile import scala.collection.mutable import scala.io.Source import scala.tools.nsc.{Global, Settings} import scala.tools.nsc.interpreter.AbstractFileClassLoader import scala.tools.nsc.io.{AbstractFile, VirtualDirectory} import scala.tools.nsc.reporters.AbstractReporter import scala.tools.nsc.util.{BatchSourceFile, Position} import java.net.URLClassLoader /** * Class for dynamically defining classes and loading them at runtime. * Based on on Twitter's Eval helper class with modifications by dramage. * * This class is pretty slow to initialize, actually. * * https://github.com/twitter/util/blob/master/util-eval/src/main/scala/com/twitter/util/Eval.scala */ object DynamicCompiler { private val compiler = new StringCompiler(0, None) def define(className : String, code : String) : Class[_] = compiler(code, className); private lazy val compilerPath = try { jarPathOfClass("scala.tools.nsc.Interpreter") } catch { case e => throw new RuntimeException("Unable to load scala interpreter from classpath (scala-compiler jar is missing?)", e) } private lazy val libPath = try { jarPathOfClass("scala.ScalaObject") } catch { case e => throw new RuntimeException("Unable to load scala base object from classpath (scala-library jar is missing?)", e) } /* * For a given FQ classname, trick the resource finder into telling us the containing jar. */ private def jarPathOfClass(className: String) = try { val resource = className.split('.').mkString("/", "/", ".class") val path = getClass.getResource(resource).getPath val indexOfFile = path.indexOf("file:") + 5 val indexOfSeparator = path.lastIndexOf('!') List(path.substring(indexOfFile, indexOfSeparator)) } /* * Try to guess our app's classpath. * This is probably fragile. */ private lazy val impliedClassPath: List[String] = { val parent = if (this.getClass.getClassLoader.isInstanceOf[URLClassLoader]) { this.getClass.getClassLoader.asInstanceOf[URLClassLoader] } else { ClassLoader.getSystemClassLoader.asInstanceOf[URLClassLoader] } val currentClassPath = parent.getURLs. map(_.toString).filter(_.startsWith("file:")).map(_.substring(5)).toList // if there's just one thing in the classpath, and it's a jar, assume an executable jar. currentClassPath ::: (if (currentClassPath.size == 1 && currentClassPath(0).endsWith(".jar")) { val jarFile = currentClassPath(0) val relativeRoot = new File(jarFile).getParentFile() val nestedClassPath = new JarFile(jarFile).getManifest.getMainAttributes.getValue("Class-Path") if (nestedClassPath eq null) { Nil } else { nestedClassPath.split(" ").map { f => new File(relativeRoot, f).getAbsolutePath }.toList } } else { Nil }) } /** * Dynamic scala compiler. Lots of (slow) state is created, so it may be advantageous to keep * around one of these and reuse it. */ private class StringCompiler(lineOffset: Int, targetDir: Option[File]) { val target = targetDir match { case Some(dir) => AbstractFile.getDirectory(dir) case None => new VirtualDirectory("(memory)", None) } val cache = new mutable.HashMap[String, Class[_]]() val settings = new Settings settings.deprecation.value = true // enable detailed deprecation warnings settings.unchecked.value = true // enable detailed unchecked warnings settings.outputDirs.setSingleOutput(target) val pathList = compilerPath ::: libPath settings.bootclasspath.value = pathList.mkString(File.pathSeparator) settings.classpath.value = (pathList ::: impliedClassPath).mkString(File.pathSeparator) val reporter = new AbstractReporter { val settings = StringCompiler.this.settings val messages = new mutable.ListBuffer[List[String]] def display(pos: Position, message: String, severity: Severity) { severity.count += 1 val severityName = severity match { case ERROR => "error: " case WARNING => "warning: " case _ => "" } messages += (severityName + "line " + (pos.line - lineOffset) + ": " + message) :: (if (pos.isDefined) { pos.inUltimateSource(pos.source).lineContent.stripLineEnd :: (" " * (pos.column - 1) + "^") :: Nil } else { Nil }) } def displayPrompt { // no. } override def reset { super.reset messages.clear() } } val global = new Global(settings, reporter) /* * Class loader for finding classes compiled by this StringCompiler. * After each reset, this class loader will not be able to find old compiled classes. */ var classLoader = new AbstractFileClassLoader(target, this.getClass.getClassLoader) def reset() { targetDir match { case None => { target.asInstanceOf[VirtualDirectory].clear } case Some(t) => { target.foreach { abstractFile => if (abstractFile.file == null || abstractFile.file.getName.endsWith(".class")) { abstractFile.delete } } } } cache.clear() reporter.reset classLoader = new AbstractFileClassLoader(target, this.getClass.getClassLoader) } object Debug { val enabled = System.getProperty("eval.debug") != null def printWithLineNumbers(code: String) { printf("Code follows (%d bytes)\n", code.length) var numLines = 0 code.lines foreach { line: String => numLines += 1 println(numLines.toString.padTo(5, ' ') + "| " + line) } } } def findClass(className: String): Option[Class[_]] = { synchronized { cache.get(className).orElse { try { val cls = classLoader.loadClass(className) cache(className) = cls Some(cls) } catch { case e: ClassNotFoundException => None } } } } /** * Compile scala code. It can be found using the above class loader. */ def apply(code: String) { if (Debug.enabled) Debug.printWithLineNumbers(code) // if you're looking for the performance hit, it's 1/2 this line... val compiler = new global.Run val sourceFiles = List(new BatchSourceFile("(inline)", code)) // ...and 1/2 this line: compiler.compileSources(sourceFiles) if (reporter.hasErrors || reporter.WARNING.count > 0) { throw new CompilerException(reporter.messages.toList) } } /** * Compile a new class, load it, and return it. Thread-safe. */ def apply(code: String, className: String, resetState: Boolean = true): Class[_] = { synchronized { if (resetState) reset() findClass(className).getOrElse { apply(code) findClass(className).get } } } } class CompilerException(val messages: List[List[String]]) extends Exception( "Compiler exception " + messages.map(_.mkString("\n")).mkString("\n")) } ================================================ FILE: src/main/scala/scalala/operators/codegen/GeneratedBinaryOp.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; package codegen; import scalala.tensor.dense._; class GeneratedBinaryOp[A, B, O<:OpType, To](override val opType : O) (implicit a : Manifest[A], b : Manifest[B], op : Manifest[O], to : Manifest[To], gen : BinaryOpGenerator[A,B,O,To]) extends BinaryOp[A,B,O,To] { lazy val instance = gen.getInstance override def apply(a : A, b : B) = instance(a,b); override def toString = gen.toString; } object GeneratedBinaryOpDefinitions { def main(args : Array[String]) { val ops = Array("OpAdd","OpSub","OpMul","OpDiv") val scalars = Array("Int","Long","Float","Double") val tensors = Array("Array","DenseVectorRow","DenseVectorCol") // returns the scalar result of combining the two operands def sr(s1 : String, s2 : String) = if (scalars.indexOf(s1) < scalars.indexOf(s2)) s2 else s1; val opsTensorTensorSame = for (t <- tensors; s1 <- scalars; s2 <- scalars; op <- ops) yield """ | implicit object %s%s%s%s%s extends GeneratedBinaryOp[%s[%s],%s[%s],%s,%s[%s]](%s) | BinaryOpRegistry.register[%s[%s],%s[%s],%s,%s[%s]] """.stripMargin.format(op,t,s1,t,s2,t,s1,t,s2,op,t,sr(s1,s2),op,t,s1,t,s2,op,t,sr(s1,s2)) val opsTensorScalar = for (t <- tensors; s1 <- scalars; s2 <- scalars; op <- ops) yield "implicit object %s%s%s%s extends GeneratedBinaryOp[%s[%s],%s,%s,%s[%s]](%s)". format(op,t,s1,s2,t,s1,s2,op,t,sr(s1,s2),op) val opsScalarTensor = for (t <- tensors; s1 <- scalars; s2 <- scalars; op <- ops) yield "implicit object %s%s%s%s extends GeneratedBinaryOp[%s,%s[%s],%s,%s[%s]](%s)". format(op,s1,t,s2,s1,t,s2,op,t,sr(s1,s2),op); for (line <- opsTensorTensorSame ++ opsTensorScalar ++ opsScalarTensor) { println(" "+line) } } } object GeneratedBinaryOps { def init() {} implicit object OpAddArrayIntArrayInt extends GeneratedBinaryOp[Array[Int],Array[Int],OpAdd,Array[Int]](OpAdd) BinaryOpRegistry.register[Array[Int],Array[Int],OpAdd,Array[Int]] implicit object OpSubArrayIntArrayInt extends GeneratedBinaryOp[Array[Int],Array[Int],OpSub,Array[Int]](OpSub) BinaryOpRegistry.register[Array[Int],Array[Int],OpSub,Array[Int]] implicit object OpMulArrayIntArrayInt extends GeneratedBinaryOp[Array[Int],Array[Int],OpMul,Array[Int]](OpMul) BinaryOpRegistry.register[Array[Int],Array[Int],OpMul,Array[Int]] implicit object OpDivArrayIntArrayInt extends GeneratedBinaryOp[Array[Int],Array[Int],OpDiv,Array[Int]](OpDiv) BinaryOpRegistry.register[Array[Int],Array[Int],OpDiv,Array[Int]] implicit object OpAddArrayIntArrayLong extends GeneratedBinaryOp[Array[Int],Array[Long],OpAdd,Array[Long]](OpAdd) BinaryOpRegistry.register[Array[Int],Array[Long],OpAdd,Array[Long]] implicit object OpSubArrayIntArrayLong extends GeneratedBinaryOp[Array[Int],Array[Long],OpSub,Array[Long]](OpSub) BinaryOpRegistry.register[Array[Int],Array[Long],OpSub,Array[Long]] implicit object OpMulArrayIntArrayLong extends GeneratedBinaryOp[Array[Int],Array[Long],OpMul,Array[Long]](OpMul) BinaryOpRegistry.register[Array[Int],Array[Long],OpMul,Array[Long]] implicit object OpDivArrayIntArrayLong extends GeneratedBinaryOp[Array[Int],Array[Long],OpDiv,Array[Long]](OpDiv) BinaryOpRegistry.register[Array[Int],Array[Long],OpDiv,Array[Long]] implicit object OpAddArrayIntArrayFloat extends GeneratedBinaryOp[Array[Int],Array[Float],OpAdd,Array[Float]](OpAdd) BinaryOpRegistry.register[Array[Int],Array[Float],OpAdd,Array[Float]] implicit object OpSubArrayIntArrayFloat extends GeneratedBinaryOp[Array[Int],Array[Float],OpSub,Array[Float]](OpSub) BinaryOpRegistry.register[Array[Int],Array[Float],OpSub,Array[Float]] implicit object OpMulArrayIntArrayFloat extends GeneratedBinaryOp[Array[Int],Array[Float],OpMul,Array[Float]](OpMul) BinaryOpRegistry.register[Array[Int],Array[Float],OpMul,Array[Float]] implicit object OpDivArrayIntArrayFloat extends GeneratedBinaryOp[Array[Int],Array[Float],OpDiv,Array[Float]](OpDiv) BinaryOpRegistry.register[Array[Int],Array[Float],OpDiv,Array[Float]] implicit object OpAddArrayIntArrayDouble extends GeneratedBinaryOp[Array[Int],Array[Double],OpAdd,Array[Double]](OpAdd) BinaryOpRegistry.register[Array[Int],Array[Double],OpAdd,Array[Double]] implicit object OpSubArrayIntArrayDouble extends GeneratedBinaryOp[Array[Int],Array[Double],OpSub,Array[Double]](OpSub) BinaryOpRegistry.register[Array[Int],Array[Double],OpSub,Array[Double]] implicit object OpMulArrayIntArrayDouble extends GeneratedBinaryOp[Array[Int],Array[Double],OpMul,Array[Double]](OpMul) BinaryOpRegistry.register[Array[Int],Array[Double],OpMul,Array[Double]] implicit object OpDivArrayIntArrayDouble extends GeneratedBinaryOp[Array[Int],Array[Double],OpDiv,Array[Double]](OpDiv) BinaryOpRegistry.register[Array[Int],Array[Double],OpDiv,Array[Double]] implicit object OpAddArrayLongArrayInt extends GeneratedBinaryOp[Array[Long],Array[Int],OpAdd,Array[Long]](OpAdd) BinaryOpRegistry.register[Array[Long],Array[Int],OpAdd,Array[Long]] implicit object OpSubArrayLongArrayInt extends GeneratedBinaryOp[Array[Long],Array[Int],OpSub,Array[Long]](OpSub) BinaryOpRegistry.register[Array[Long],Array[Int],OpSub,Array[Long]] implicit object OpMulArrayLongArrayInt extends GeneratedBinaryOp[Array[Long],Array[Int],OpMul,Array[Long]](OpMul) BinaryOpRegistry.register[Array[Long],Array[Int],OpMul,Array[Long]] implicit object OpDivArrayLongArrayInt extends GeneratedBinaryOp[Array[Long],Array[Int],OpDiv,Array[Long]](OpDiv) BinaryOpRegistry.register[Array[Long],Array[Int],OpDiv,Array[Long]] implicit object OpAddArrayLongArrayLong extends GeneratedBinaryOp[Array[Long],Array[Long],OpAdd,Array[Long]](OpAdd) BinaryOpRegistry.register[Array[Long],Array[Long],OpAdd,Array[Long]] implicit object OpSubArrayLongArrayLong extends GeneratedBinaryOp[Array[Long],Array[Long],OpSub,Array[Long]](OpSub) BinaryOpRegistry.register[Array[Long],Array[Long],OpSub,Array[Long]] implicit object OpMulArrayLongArrayLong extends GeneratedBinaryOp[Array[Long],Array[Long],OpMul,Array[Long]](OpMul) BinaryOpRegistry.register[Array[Long],Array[Long],OpMul,Array[Long]] implicit object OpDivArrayLongArrayLong extends GeneratedBinaryOp[Array[Long],Array[Long],OpDiv,Array[Long]](OpDiv) BinaryOpRegistry.register[Array[Long],Array[Long],OpDiv,Array[Long]] implicit object OpAddArrayLongArrayFloat extends GeneratedBinaryOp[Array[Long],Array[Float],OpAdd,Array[Float]](OpAdd) BinaryOpRegistry.register[Array[Long],Array[Float],OpAdd,Array[Float]] implicit object OpSubArrayLongArrayFloat extends GeneratedBinaryOp[Array[Long],Array[Float],OpSub,Array[Float]](OpSub) BinaryOpRegistry.register[Array[Long],Array[Float],OpSub,Array[Float]] implicit object OpMulArrayLongArrayFloat extends GeneratedBinaryOp[Array[Long],Array[Float],OpMul,Array[Float]](OpMul) BinaryOpRegistry.register[Array[Long],Array[Float],OpMul,Array[Float]] implicit object OpDivArrayLongArrayFloat extends GeneratedBinaryOp[Array[Long],Array[Float],OpDiv,Array[Float]](OpDiv) BinaryOpRegistry.register[Array[Long],Array[Float],OpDiv,Array[Float]] implicit object OpAddArrayLongArrayDouble extends GeneratedBinaryOp[Array[Long],Array[Double],OpAdd,Array[Double]](OpAdd) BinaryOpRegistry.register[Array[Long],Array[Double],OpAdd,Array[Double]] implicit object OpSubArrayLongArrayDouble extends GeneratedBinaryOp[Array[Long],Array[Double],OpSub,Array[Double]](OpSub) BinaryOpRegistry.register[Array[Long],Array[Double],OpSub,Array[Double]] implicit object OpMulArrayLongArrayDouble extends GeneratedBinaryOp[Array[Long],Array[Double],OpMul,Array[Double]](OpMul) BinaryOpRegistry.register[Array[Long],Array[Double],OpMul,Array[Double]] implicit object OpDivArrayLongArrayDouble extends GeneratedBinaryOp[Array[Long],Array[Double],OpDiv,Array[Double]](OpDiv) BinaryOpRegistry.register[Array[Long],Array[Double],OpDiv,Array[Double]] implicit object OpAddArrayFloatArrayInt extends GeneratedBinaryOp[Array[Float],Array[Int],OpAdd,Array[Float]](OpAdd) BinaryOpRegistry.register[Array[Float],Array[Int],OpAdd,Array[Float]] implicit object OpSubArrayFloatArrayInt extends GeneratedBinaryOp[Array[Float],Array[Int],OpSub,Array[Float]](OpSub) BinaryOpRegistry.register[Array[Float],Array[Int],OpSub,Array[Float]] implicit object OpMulArrayFloatArrayInt extends GeneratedBinaryOp[Array[Float],Array[Int],OpMul,Array[Float]](OpMul) BinaryOpRegistry.register[Array[Float],Array[Int],OpMul,Array[Float]] implicit object OpDivArrayFloatArrayInt extends GeneratedBinaryOp[Array[Float],Array[Int],OpDiv,Array[Float]](OpDiv) BinaryOpRegistry.register[Array[Float],Array[Int],OpDiv,Array[Float]] implicit object OpAddArrayFloatArrayLong extends GeneratedBinaryOp[Array[Float],Array[Long],OpAdd,Array[Float]](OpAdd) BinaryOpRegistry.register[Array[Float],Array[Long],OpAdd,Array[Float]] implicit object OpSubArrayFloatArrayLong extends GeneratedBinaryOp[Array[Float],Array[Long],OpSub,Array[Float]](OpSub) BinaryOpRegistry.register[Array[Float],Array[Long],OpSub,Array[Float]] implicit object OpMulArrayFloatArrayLong extends GeneratedBinaryOp[Array[Float],Array[Long],OpMul,Array[Float]](OpMul) BinaryOpRegistry.register[Array[Float],Array[Long],OpMul,Array[Float]] implicit object OpDivArrayFloatArrayLong extends GeneratedBinaryOp[Array[Float],Array[Long],OpDiv,Array[Float]](OpDiv) BinaryOpRegistry.register[Array[Float],Array[Long],OpDiv,Array[Float]] implicit object OpAddArrayFloatArrayFloat extends GeneratedBinaryOp[Array[Float],Array[Float],OpAdd,Array[Float]](OpAdd) BinaryOpRegistry.register[Array[Float],Array[Float],OpAdd,Array[Float]] implicit object OpSubArrayFloatArrayFloat extends GeneratedBinaryOp[Array[Float],Array[Float],OpSub,Array[Float]](OpSub) BinaryOpRegistry.register[Array[Float],Array[Float],OpSub,Array[Float]] implicit object OpMulArrayFloatArrayFloat extends GeneratedBinaryOp[Array[Float],Array[Float],OpMul,Array[Float]](OpMul) BinaryOpRegistry.register[Array[Float],Array[Float],OpMul,Array[Float]] implicit object OpDivArrayFloatArrayFloat extends GeneratedBinaryOp[Array[Float],Array[Float],OpDiv,Array[Float]](OpDiv) BinaryOpRegistry.register[Array[Float],Array[Float],OpDiv,Array[Float]] implicit object OpAddArrayFloatArrayDouble extends GeneratedBinaryOp[Array[Float],Array[Double],OpAdd,Array[Double]](OpAdd) BinaryOpRegistry.register[Array[Float],Array[Double],OpAdd,Array[Double]] implicit object OpSubArrayFloatArrayDouble extends GeneratedBinaryOp[Array[Float],Array[Double],OpSub,Array[Double]](OpSub) BinaryOpRegistry.register[Array[Float],Array[Double],OpSub,Array[Double]] implicit object OpMulArrayFloatArrayDouble extends GeneratedBinaryOp[Array[Float],Array[Double],OpMul,Array[Double]](OpMul) BinaryOpRegistry.register[Array[Float],Array[Double],OpMul,Array[Double]] implicit object OpDivArrayFloatArrayDouble extends GeneratedBinaryOp[Array[Float],Array[Double],OpDiv,Array[Double]](OpDiv) BinaryOpRegistry.register[Array[Float],Array[Double],OpDiv,Array[Double]] implicit object OpAddArrayDoubleArrayInt extends GeneratedBinaryOp[Array[Double],Array[Int],OpAdd,Array[Double]](OpAdd) BinaryOpRegistry.register[Array[Double],Array[Int],OpAdd,Array[Double]] implicit object OpSubArrayDoubleArrayInt extends GeneratedBinaryOp[Array[Double],Array[Int],OpSub,Array[Double]](OpSub) BinaryOpRegistry.register[Array[Double],Array[Int],OpSub,Array[Double]] implicit object OpMulArrayDoubleArrayInt extends GeneratedBinaryOp[Array[Double],Array[Int],OpMul,Array[Double]](OpMul) BinaryOpRegistry.register[Array[Double],Array[Int],OpMul,Array[Double]] implicit object OpDivArrayDoubleArrayInt extends GeneratedBinaryOp[Array[Double],Array[Int],OpDiv,Array[Double]](OpDiv) BinaryOpRegistry.register[Array[Double],Array[Int],OpDiv,Array[Double]] implicit object OpAddArrayDoubleArrayLong extends GeneratedBinaryOp[Array[Double],Array[Long],OpAdd,Array[Double]](OpAdd) BinaryOpRegistry.register[Array[Double],Array[Long],OpAdd,Array[Double]] implicit object OpSubArrayDoubleArrayLong extends GeneratedBinaryOp[Array[Double],Array[Long],OpSub,Array[Double]](OpSub) BinaryOpRegistry.register[Array[Double],Array[Long],OpSub,Array[Double]] implicit object OpMulArrayDoubleArrayLong extends GeneratedBinaryOp[Array[Double],Array[Long],OpMul,Array[Double]](OpMul) BinaryOpRegistry.register[Array[Double],Array[Long],OpMul,Array[Double]] implicit object OpDivArrayDoubleArrayLong extends GeneratedBinaryOp[Array[Double],Array[Long],OpDiv,Array[Double]](OpDiv) BinaryOpRegistry.register[Array[Double],Array[Long],OpDiv,Array[Double]] implicit object OpAddArrayDoubleArrayFloat extends GeneratedBinaryOp[Array[Double],Array[Float],OpAdd,Array[Double]](OpAdd) BinaryOpRegistry.register[Array[Double],Array[Float],OpAdd,Array[Double]] implicit object OpSubArrayDoubleArrayFloat extends GeneratedBinaryOp[Array[Double],Array[Float],OpSub,Array[Double]](OpSub) BinaryOpRegistry.register[Array[Double],Array[Float],OpSub,Array[Double]] implicit object OpMulArrayDoubleArrayFloat extends GeneratedBinaryOp[Array[Double],Array[Float],OpMul,Array[Double]](OpMul) BinaryOpRegistry.register[Array[Double],Array[Float],OpMul,Array[Double]] implicit object OpDivArrayDoubleArrayFloat extends GeneratedBinaryOp[Array[Double],Array[Float],OpDiv,Array[Double]](OpDiv) BinaryOpRegistry.register[Array[Double],Array[Float],OpDiv,Array[Double]] implicit object OpAddArrayDoubleArrayDouble extends GeneratedBinaryOp[Array[Double],Array[Double],OpAdd,Array[Double]](OpAdd) BinaryOpRegistry.register[Array[Double],Array[Double],OpAdd,Array[Double]] implicit object OpSubArrayDoubleArrayDouble extends GeneratedBinaryOp[Array[Double],Array[Double],OpSub,Array[Double]](OpSub) BinaryOpRegistry.register[Array[Double],Array[Double],OpSub,Array[Double]] implicit object OpMulArrayDoubleArrayDouble extends GeneratedBinaryOp[Array[Double],Array[Double],OpMul,Array[Double]](OpMul) BinaryOpRegistry.register[Array[Double],Array[Double],OpMul,Array[Double]] implicit object OpDivArrayDoubleArrayDouble extends GeneratedBinaryOp[Array[Double],Array[Double],OpDiv,Array[Double]](OpDiv) BinaryOpRegistry.register[Array[Double],Array[Double],OpDiv,Array[Double]] implicit object OpAddDenseVectorRowIntDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Int],OpAdd,DenseVectorRow[Int]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Int],OpAdd,DenseVectorRow[Int]] implicit object OpSubDenseVectorRowIntDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Int],OpSub,DenseVectorRow[Int]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Int],OpSub,DenseVectorRow[Int]] implicit object OpMulDenseVectorRowIntDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Int],OpMul,DenseVectorRow[Int]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Int],OpMul,DenseVectorRow[Int]] implicit object OpDivDenseVectorRowIntDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Int],OpDiv,DenseVectorRow[Int]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Int],OpDiv,DenseVectorRow[Int]] implicit object OpAddDenseVectorRowIntDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Long],OpAdd,DenseVectorRow[Long]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Long],OpAdd,DenseVectorRow[Long]] implicit object OpSubDenseVectorRowIntDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Long],OpSub,DenseVectorRow[Long]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Long],OpSub,DenseVectorRow[Long]] implicit object OpMulDenseVectorRowIntDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Long],OpMul,DenseVectorRow[Long]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Long],OpMul,DenseVectorRow[Long]] implicit object OpDivDenseVectorRowIntDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Long],OpDiv,DenseVectorRow[Long]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Long],OpDiv,DenseVectorRow[Long]] implicit object OpAddDenseVectorRowIntDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]] implicit object OpSubDenseVectorRowIntDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Float],OpSub,DenseVectorRow[Float]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Float],OpSub,DenseVectorRow[Float]] implicit object OpMulDenseVectorRowIntDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Float],OpMul,DenseVectorRow[Float]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Float],OpMul,DenseVectorRow[Float]] implicit object OpDivDenseVectorRowIntDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]] implicit object OpAddDenseVectorRowIntDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]] implicit object OpSubDenseVectorRowIntDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Double],OpSub,DenseVectorRow[Double]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Double],OpSub,DenseVectorRow[Double]] implicit object OpMulDenseVectorRowIntDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Double],OpMul,DenseVectorRow[Double]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Double],OpMul,DenseVectorRow[Double]] implicit object OpDivDenseVectorRowIntDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Int],DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Int],DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]] implicit object OpAddDenseVectorRowLongDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Int],OpAdd,DenseVectorRow[Long]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Int],OpAdd,DenseVectorRow[Long]] implicit object OpSubDenseVectorRowLongDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Int],OpSub,DenseVectorRow[Long]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Int],OpSub,DenseVectorRow[Long]] implicit object OpMulDenseVectorRowLongDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Int],OpMul,DenseVectorRow[Long]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Int],OpMul,DenseVectorRow[Long]] implicit object OpDivDenseVectorRowLongDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Int],OpDiv,DenseVectorRow[Long]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Int],OpDiv,DenseVectorRow[Long]] implicit object OpAddDenseVectorRowLongDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Long],OpAdd,DenseVectorRow[Long]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Long],OpAdd,DenseVectorRow[Long]] implicit object OpSubDenseVectorRowLongDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Long],OpSub,DenseVectorRow[Long]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Long],OpSub,DenseVectorRow[Long]] implicit object OpMulDenseVectorRowLongDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Long],OpMul,DenseVectorRow[Long]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Long],OpMul,DenseVectorRow[Long]] implicit object OpDivDenseVectorRowLongDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Long],OpDiv,DenseVectorRow[Long]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Long],OpDiv,DenseVectorRow[Long]] implicit object OpAddDenseVectorRowLongDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]] implicit object OpSubDenseVectorRowLongDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Float],OpSub,DenseVectorRow[Float]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Float],OpSub,DenseVectorRow[Float]] implicit object OpMulDenseVectorRowLongDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Float],OpMul,DenseVectorRow[Float]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Float],OpMul,DenseVectorRow[Float]] implicit object OpDivDenseVectorRowLongDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]] implicit object OpAddDenseVectorRowLongDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]] implicit object OpSubDenseVectorRowLongDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Double],OpSub,DenseVectorRow[Double]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Double],OpSub,DenseVectorRow[Double]] implicit object OpMulDenseVectorRowLongDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Double],OpMul,DenseVectorRow[Double]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Double],OpMul,DenseVectorRow[Double]] implicit object OpDivDenseVectorRowLongDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Long],DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Long],DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]] implicit object OpAddDenseVectorRowFloatDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Int],OpAdd,DenseVectorRow[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Int],OpAdd,DenseVectorRow[Float]] implicit object OpSubDenseVectorRowFloatDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Int],OpSub,DenseVectorRow[Float]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Int],OpSub,DenseVectorRow[Float]] implicit object OpMulDenseVectorRowFloatDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Int],OpMul,DenseVectorRow[Float]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Int],OpMul,DenseVectorRow[Float]] implicit object OpDivDenseVectorRowFloatDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Int],OpDiv,DenseVectorRow[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Int],OpDiv,DenseVectorRow[Float]] implicit object OpAddDenseVectorRowFloatDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Long],OpAdd,DenseVectorRow[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Long],OpAdd,DenseVectorRow[Float]] implicit object OpSubDenseVectorRowFloatDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Long],OpSub,DenseVectorRow[Float]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Long],OpSub,DenseVectorRow[Float]] implicit object OpMulDenseVectorRowFloatDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Long],OpMul,DenseVectorRow[Float]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Long],OpMul,DenseVectorRow[Float]] implicit object OpDivDenseVectorRowFloatDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Long],OpDiv,DenseVectorRow[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Long],OpDiv,DenseVectorRow[Float]] implicit object OpAddDenseVectorRowFloatDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]] implicit object OpSubDenseVectorRowFloatDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Float],OpSub,DenseVectorRow[Float]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Float],OpSub,DenseVectorRow[Float]] implicit object OpMulDenseVectorRowFloatDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Float],OpMul,DenseVectorRow[Float]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Float],OpMul,DenseVectorRow[Float]] implicit object OpDivDenseVectorRowFloatDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]] implicit object OpAddDenseVectorRowFloatDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]] implicit object OpSubDenseVectorRowFloatDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Double],OpSub,DenseVectorRow[Double]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Double],OpSub,DenseVectorRow[Double]] implicit object OpMulDenseVectorRowFloatDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Double],OpMul,DenseVectorRow[Double]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Double],OpMul,DenseVectorRow[Double]] implicit object OpDivDenseVectorRowFloatDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Float],DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Float],DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]] implicit object OpAddDenseVectorRowDoubleDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Int],OpAdd,DenseVectorRow[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Int],OpAdd,DenseVectorRow[Double]] implicit object OpSubDenseVectorRowDoubleDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Int],OpSub,DenseVectorRow[Double]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Int],OpSub,DenseVectorRow[Double]] implicit object OpMulDenseVectorRowDoubleDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Int],OpMul,DenseVectorRow[Double]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Int],OpMul,DenseVectorRow[Double]] implicit object OpDivDenseVectorRowDoubleDenseVectorRowInt extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Int],OpDiv,DenseVectorRow[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Int],OpDiv,DenseVectorRow[Double]] implicit object OpAddDenseVectorRowDoubleDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Long],OpAdd,DenseVectorRow[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Long],OpAdd,DenseVectorRow[Double]] implicit object OpSubDenseVectorRowDoubleDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Long],OpSub,DenseVectorRow[Double]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Long],OpSub,DenseVectorRow[Double]] implicit object OpMulDenseVectorRowDoubleDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Long],OpMul,DenseVectorRow[Double]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Long],OpMul,DenseVectorRow[Double]] implicit object OpDivDenseVectorRowDoubleDenseVectorRowLong extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Long],OpDiv,DenseVectorRow[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Long],OpDiv,DenseVectorRow[Double]] implicit object OpAddDenseVectorRowDoubleDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Float],OpAdd,DenseVectorRow[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Float],OpAdd,DenseVectorRow[Double]] implicit object OpSubDenseVectorRowDoubleDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Float],OpSub,DenseVectorRow[Double]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Float],OpSub,DenseVectorRow[Double]] implicit object OpMulDenseVectorRowDoubleDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Float],OpMul,DenseVectorRow[Double]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Float],OpMul,DenseVectorRow[Double]] implicit object OpDivDenseVectorRowDoubleDenseVectorRowFloat extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Float],OpDiv,DenseVectorRow[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Float],OpDiv,DenseVectorRow[Double]] implicit object OpAddDenseVectorRowDoubleDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]] implicit object OpSubDenseVectorRowDoubleDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Double],OpSub,DenseVectorRow[Double]](OpSub) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Double],OpSub,DenseVectorRow[Double]] implicit object OpMulDenseVectorRowDoubleDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Double],OpMul,DenseVectorRow[Double]](OpMul) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Double],OpMul,DenseVectorRow[Double]] implicit object OpDivDenseVectorRowDoubleDenseVectorRowDouble extends GeneratedBinaryOp[DenseVectorRow[Double],DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorRow[Double],DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]] implicit object OpAddDenseVectorColIntDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Int],OpAdd,DenseVectorCol[Int]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Int],OpAdd,DenseVectorCol[Int]] implicit object OpSubDenseVectorColIntDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Int],OpSub,DenseVectorCol[Int]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Int],OpSub,DenseVectorCol[Int]] implicit object OpMulDenseVectorColIntDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Int],OpMul,DenseVectorCol[Int]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Int],OpMul,DenseVectorCol[Int]] implicit object OpDivDenseVectorColIntDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Int],OpDiv,DenseVectorCol[Int]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Int],OpDiv,DenseVectorCol[Int]] implicit object OpAddDenseVectorColIntDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Long],OpAdd,DenseVectorCol[Long]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Long],OpAdd,DenseVectorCol[Long]] implicit object OpSubDenseVectorColIntDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Long],OpSub,DenseVectorCol[Long]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Long],OpSub,DenseVectorCol[Long]] implicit object OpMulDenseVectorColIntDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Long],OpMul,DenseVectorCol[Long]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Long],OpMul,DenseVectorCol[Long]] implicit object OpDivDenseVectorColIntDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Long],OpDiv,DenseVectorCol[Long]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Long],OpDiv,DenseVectorCol[Long]] implicit object OpAddDenseVectorColIntDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]] implicit object OpSubDenseVectorColIntDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Float],OpSub,DenseVectorCol[Float]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Float],OpSub,DenseVectorCol[Float]] implicit object OpMulDenseVectorColIntDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Float],OpMul,DenseVectorCol[Float]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Float],OpMul,DenseVectorCol[Float]] implicit object OpDivDenseVectorColIntDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]] implicit object OpAddDenseVectorColIntDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]] implicit object OpSubDenseVectorColIntDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Double],OpSub,DenseVectorCol[Double]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Double],OpSub,DenseVectorCol[Double]] implicit object OpMulDenseVectorColIntDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Double],OpMul,DenseVectorCol[Double]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Double],OpMul,DenseVectorCol[Double]] implicit object OpDivDenseVectorColIntDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Int],DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Int],DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]] implicit object OpAddDenseVectorColLongDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Int],OpAdd,DenseVectorCol[Long]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Int],OpAdd,DenseVectorCol[Long]] implicit object OpSubDenseVectorColLongDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Int],OpSub,DenseVectorCol[Long]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Int],OpSub,DenseVectorCol[Long]] implicit object OpMulDenseVectorColLongDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Int],OpMul,DenseVectorCol[Long]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Int],OpMul,DenseVectorCol[Long]] implicit object OpDivDenseVectorColLongDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Int],OpDiv,DenseVectorCol[Long]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Int],OpDiv,DenseVectorCol[Long]] implicit object OpAddDenseVectorColLongDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Long],OpAdd,DenseVectorCol[Long]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Long],OpAdd,DenseVectorCol[Long]] implicit object OpSubDenseVectorColLongDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Long],OpSub,DenseVectorCol[Long]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Long],OpSub,DenseVectorCol[Long]] implicit object OpMulDenseVectorColLongDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Long],OpMul,DenseVectorCol[Long]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Long],OpMul,DenseVectorCol[Long]] implicit object OpDivDenseVectorColLongDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Long],OpDiv,DenseVectorCol[Long]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Long],OpDiv,DenseVectorCol[Long]] implicit object OpAddDenseVectorColLongDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]] implicit object OpSubDenseVectorColLongDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Float],OpSub,DenseVectorCol[Float]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Float],OpSub,DenseVectorCol[Float]] implicit object OpMulDenseVectorColLongDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Float],OpMul,DenseVectorCol[Float]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Float],OpMul,DenseVectorCol[Float]] implicit object OpDivDenseVectorColLongDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]] implicit object OpAddDenseVectorColLongDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]] implicit object OpSubDenseVectorColLongDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Double],OpSub,DenseVectorCol[Double]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Double],OpSub,DenseVectorCol[Double]] implicit object OpMulDenseVectorColLongDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Double],OpMul,DenseVectorCol[Double]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Double],OpMul,DenseVectorCol[Double]] implicit object OpDivDenseVectorColLongDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Long],DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Long],DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]] implicit object OpAddDenseVectorColFloatDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Int],OpAdd,DenseVectorCol[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Int],OpAdd,DenseVectorCol[Float]] implicit object OpSubDenseVectorColFloatDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Int],OpSub,DenseVectorCol[Float]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Int],OpSub,DenseVectorCol[Float]] implicit object OpMulDenseVectorColFloatDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Int],OpMul,DenseVectorCol[Float]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Int],OpMul,DenseVectorCol[Float]] implicit object OpDivDenseVectorColFloatDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Int],OpDiv,DenseVectorCol[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Int],OpDiv,DenseVectorCol[Float]] implicit object OpAddDenseVectorColFloatDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Long],OpAdd,DenseVectorCol[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Long],OpAdd,DenseVectorCol[Float]] implicit object OpSubDenseVectorColFloatDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Long],OpSub,DenseVectorCol[Float]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Long],OpSub,DenseVectorCol[Float]] implicit object OpMulDenseVectorColFloatDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Long],OpMul,DenseVectorCol[Float]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Long],OpMul,DenseVectorCol[Float]] implicit object OpDivDenseVectorColFloatDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Long],OpDiv,DenseVectorCol[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Long],OpDiv,DenseVectorCol[Float]] implicit object OpAddDenseVectorColFloatDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]] implicit object OpSubDenseVectorColFloatDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Float],OpSub,DenseVectorCol[Float]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Float],OpSub,DenseVectorCol[Float]] implicit object OpMulDenseVectorColFloatDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Float],OpMul,DenseVectorCol[Float]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Float],OpMul,DenseVectorCol[Float]] implicit object OpDivDenseVectorColFloatDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]] implicit object OpAddDenseVectorColFloatDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]] implicit object OpSubDenseVectorColFloatDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Double],OpSub,DenseVectorCol[Double]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Double],OpSub,DenseVectorCol[Double]] implicit object OpMulDenseVectorColFloatDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Double],OpMul,DenseVectorCol[Double]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Double],OpMul,DenseVectorCol[Double]] implicit object OpDivDenseVectorColFloatDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Float],DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Float],DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]] implicit object OpAddDenseVectorColDoubleDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Int],OpAdd,DenseVectorCol[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Int],OpAdd,DenseVectorCol[Double]] implicit object OpSubDenseVectorColDoubleDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Int],OpSub,DenseVectorCol[Double]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Int],OpSub,DenseVectorCol[Double]] implicit object OpMulDenseVectorColDoubleDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Int],OpMul,DenseVectorCol[Double]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Int],OpMul,DenseVectorCol[Double]] implicit object OpDivDenseVectorColDoubleDenseVectorColInt extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Int],OpDiv,DenseVectorCol[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Int],OpDiv,DenseVectorCol[Double]] implicit object OpAddDenseVectorColDoubleDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Long],OpAdd,DenseVectorCol[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Long],OpAdd,DenseVectorCol[Double]] implicit object OpSubDenseVectorColDoubleDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Long],OpSub,DenseVectorCol[Double]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Long],OpSub,DenseVectorCol[Double]] implicit object OpMulDenseVectorColDoubleDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Long],OpMul,DenseVectorCol[Double]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Long],OpMul,DenseVectorCol[Double]] implicit object OpDivDenseVectorColDoubleDenseVectorColLong extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Long],OpDiv,DenseVectorCol[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Long],OpDiv,DenseVectorCol[Double]] implicit object OpAddDenseVectorColDoubleDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Float],OpAdd,DenseVectorCol[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Float],OpAdd,DenseVectorCol[Double]] implicit object OpSubDenseVectorColDoubleDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Float],OpSub,DenseVectorCol[Double]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Float],OpSub,DenseVectorCol[Double]] implicit object OpMulDenseVectorColDoubleDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Float],OpMul,DenseVectorCol[Double]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Float],OpMul,DenseVectorCol[Double]] implicit object OpDivDenseVectorColDoubleDenseVectorColFloat extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Float],OpDiv,DenseVectorCol[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Float],OpDiv,DenseVectorCol[Double]] implicit object OpAddDenseVectorColDoubleDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]](OpAdd) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]] implicit object OpSubDenseVectorColDoubleDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Double],OpSub,DenseVectorCol[Double]](OpSub) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Double],OpSub,DenseVectorCol[Double]] implicit object OpMulDenseVectorColDoubleDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Double],OpMul,DenseVectorCol[Double]](OpMul) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Double],OpMul,DenseVectorCol[Double]] implicit object OpDivDenseVectorColDoubleDenseVectorColDouble extends GeneratedBinaryOp[DenseVectorCol[Double],DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]](OpDiv) BinaryOpRegistry.register[DenseVectorCol[Double],DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]] implicit object OpAddArrayIntInt extends GeneratedBinaryOp[Array[Int],Int,OpAdd,Array[Int]](OpAdd) implicit object OpSubArrayIntInt extends GeneratedBinaryOp[Array[Int],Int,OpSub,Array[Int]](OpSub) implicit object OpMulArrayIntInt extends GeneratedBinaryOp[Array[Int],Int,OpMul,Array[Int]](OpMul) implicit object OpDivArrayIntInt extends GeneratedBinaryOp[Array[Int],Int,OpDiv,Array[Int]](OpDiv) implicit object OpAddArrayIntLong extends GeneratedBinaryOp[Array[Int],Long,OpAdd,Array[Long]](OpAdd) implicit object OpSubArrayIntLong extends GeneratedBinaryOp[Array[Int],Long,OpSub,Array[Long]](OpSub) implicit object OpMulArrayIntLong extends GeneratedBinaryOp[Array[Int],Long,OpMul,Array[Long]](OpMul) implicit object OpDivArrayIntLong extends GeneratedBinaryOp[Array[Int],Long,OpDiv,Array[Long]](OpDiv) implicit object OpAddArrayIntFloat extends GeneratedBinaryOp[Array[Int],Float,OpAdd,Array[Float]](OpAdd) implicit object OpSubArrayIntFloat extends GeneratedBinaryOp[Array[Int],Float,OpSub,Array[Float]](OpSub) implicit object OpMulArrayIntFloat extends GeneratedBinaryOp[Array[Int],Float,OpMul,Array[Float]](OpMul) implicit object OpDivArrayIntFloat extends GeneratedBinaryOp[Array[Int],Float,OpDiv,Array[Float]](OpDiv) implicit object OpAddArrayIntDouble extends GeneratedBinaryOp[Array[Int],Double,OpAdd,Array[Double]](OpAdd) implicit object OpSubArrayIntDouble extends GeneratedBinaryOp[Array[Int],Double,OpSub,Array[Double]](OpSub) implicit object OpMulArrayIntDouble extends GeneratedBinaryOp[Array[Int],Double,OpMul,Array[Double]](OpMul) implicit object OpDivArrayIntDouble extends GeneratedBinaryOp[Array[Int],Double,OpDiv,Array[Double]](OpDiv) implicit object OpAddArrayLongInt extends GeneratedBinaryOp[Array[Long],Int,OpAdd,Array[Long]](OpAdd) implicit object OpSubArrayLongInt extends GeneratedBinaryOp[Array[Long],Int,OpSub,Array[Long]](OpSub) implicit object OpMulArrayLongInt extends GeneratedBinaryOp[Array[Long],Int,OpMul,Array[Long]](OpMul) implicit object OpDivArrayLongInt extends GeneratedBinaryOp[Array[Long],Int,OpDiv,Array[Long]](OpDiv) implicit object OpAddArrayLongLong extends GeneratedBinaryOp[Array[Long],Long,OpAdd,Array[Long]](OpAdd) implicit object OpSubArrayLongLong extends GeneratedBinaryOp[Array[Long],Long,OpSub,Array[Long]](OpSub) implicit object OpMulArrayLongLong extends GeneratedBinaryOp[Array[Long],Long,OpMul,Array[Long]](OpMul) implicit object OpDivArrayLongLong extends GeneratedBinaryOp[Array[Long],Long,OpDiv,Array[Long]](OpDiv) implicit object OpAddArrayLongFloat extends GeneratedBinaryOp[Array[Long],Float,OpAdd,Array[Float]](OpAdd) implicit object OpSubArrayLongFloat extends GeneratedBinaryOp[Array[Long],Float,OpSub,Array[Float]](OpSub) implicit object OpMulArrayLongFloat extends GeneratedBinaryOp[Array[Long],Float,OpMul,Array[Float]](OpMul) implicit object OpDivArrayLongFloat extends GeneratedBinaryOp[Array[Long],Float,OpDiv,Array[Float]](OpDiv) implicit object OpAddArrayLongDouble extends GeneratedBinaryOp[Array[Long],Double,OpAdd,Array[Double]](OpAdd) implicit object OpSubArrayLongDouble extends GeneratedBinaryOp[Array[Long],Double,OpSub,Array[Double]](OpSub) implicit object OpMulArrayLongDouble extends GeneratedBinaryOp[Array[Long],Double,OpMul,Array[Double]](OpMul) implicit object OpDivArrayLongDouble extends GeneratedBinaryOp[Array[Long],Double,OpDiv,Array[Double]](OpDiv) implicit object OpAddArrayFloatInt extends GeneratedBinaryOp[Array[Float],Int,OpAdd,Array[Float]](OpAdd) implicit object OpSubArrayFloatInt extends GeneratedBinaryOp[Array[Float],Int,OpSub,Array[Float]](OpSub) implicit object OpMulArrayFloatInt extends GeneratedBinaryOp[Array[Float],Int,OpMul,Array[Float]](OpMul) implicit object OpDivArrayFloatInt extends GeneratedBinaryOp[Array[Float],Int,OpDiv,Array[Float]](OpDiv) implicit object OpAddArrayFloatLong extends GeneratedBinaryOp[Array[Float],Long,OpAdd,Array[Float]](OpAdd) implicit object OpSubArrayFloatLong extends GeneratedBinaryOp[Array[Float],Long,OpSub,Array[Float]](OpSub) implicit object OpMulArrayFloatLong extends GeneratedBinaryOp[Array[Float],Long,OpMul,Array[Float]](OpMul) implicit object OpDivArrayFloatLong extends GeneratedBinaryOp[Array[Float],Long,OpDiv,Array[Float]](OpDiv) implicit object OpAddArrayFloatFloat extends GeneratedBinaryOp[Array[Float],Float,OpAdd,Array[Float]](OpAdd) implicit object OpSubArrayFloatFloat extends GeneratedBinaryOp[Array[Float],Float,OpSub,Array[Float]](OpSub) implicit object OpMulArrayFloatFloat extends GeneratedBinaryOp[Array[Float],Float,OpMul,Array[Float]](OpMul) implicit object OpDivArrayFloatFloat extends GeneratedBinaryOp[Array[Float],Float,OpDiv,Array[Float]](OpDiv) implicit object OpAddArrayFloatDouble extends GeneratedBinaryOp[Array[Float],Double,OpAdd,Array[Double]](OpAdd) implicit object OpSubArrayFloatDouble extends GeneratedBinaryOp[Array[Float],Double,OpSub,Array[Double]](OpSub) implicit object OpMulArrayFloatDouble extends GeneratedBinaryOp[Array[Float],Double,OpMul,Array[Double]](OpMul) implicit object OpDivArrayFloatDouble extends GeneratedBinaryOp[Array[Float],Double,OpDiv,Array[Double]](OpDiv) implicit object OpAddArrayDoubleInt extends GeneratedBinaryOp[Array[Double],Int,OpAdd,Array[Double]](OpAdd) implicit object OpSubArrayDoubleInt extends GeneratedBinaryOp[Array[Double],Int,OpSub,Array[Double]](OpSub) implicit object OpMulArrayDoubleInt extends GeneratedBinaryOp[Array[Double],Int,OpMul,Array[Double]](OpMul) implicit object OpDivArrayDoubleInt extends GeneratedBinaryOp[Array[Double],Int,OpDiv,Array[Double]](OpDiv) implicit object OpAddArrayDoubleLong extends GeneratedBinaryOp[Array[Double],Long,OpAdd,Array[Double]](OpAdd) implicit object OpSubArrayDoubleLong extends GeneratedBinaryOp[Array[Double],Long,OpSub,Array[Double]](OpSub) implicit object OpMulArrayDoubleLong extends GeneratedBinaryOp[Array[Double],Long,OpMul,Array[Double]](OpMul) implicit object OpDivArrayDoubleLong extends GeneratedBinaryOp[Array[Double],Long,OpDiv,Array[Double]](OpDiv) implicit object OpAddArrayDoubleFloat extends GeneratedBinaryOp[Array[Double],Float,OpAdd,Array[Double]](OpAdd) implicit object OpSubArrayDoubleFloat extends GeneratedBinaryOp[Array[Double],Float,OpSub,Array[Double]](OpSub) implicit object OpMulArrayDoubleFloat extends GeneratedBinaryOp[Array[Double],Float,OpMul,Array[Double]](OpMul) implicit object OpDivArrayDoubleFloat extends GeneratedBinaryOp[Array[Double],Float,OpDiv,Array[Double]](OpDiv) implicit object OpAddArrayDoubleDouble extends GeneratedBinaryOp[Array[Double],Double,OpAdd,Array[Double]](OpAdd) implicit object OpSubArrayDoubleDouble extends GeneratedBinaryOp[Array[Double],Double,OpSub,Array[Double]](OpSub) implicit object OpMulArrayDoubleDouble extends GeneratedBinaryOp[Array[Double],Double,OpMul,Array[Double]](OpMul) implicit object OpDivArrayDoubleDouble extends GeneratedBinaryOp[Array[Double],Double,OpDiv,Array[Double]](OpDiv) implicit object OpAddDenseVectorRowIntInt extends GeneratedBinaryOp[DenseVectorRow[Int],Int,OpAdd,DenseVectorRow[Int]](OpAdd) implicit object OpSubDenseVectorRowIntInt extends GeneratedBinaryOp[DenseVectorRow[Int],Int,OpSub,DenseVectorRow[Int]](OpSub) implicit object OpMulDenseVectorRowIntInt extends GeneratedBinaryOp[DenseVectorRow[Int],Int,OpMul,DenseVectorRow[Int]](OpMul) implicit object OpDivDenseVectorRowIntInt extends GeneratedBinaryOp[DenseVectorRow[Int],Int,OpDiv,DenseVectorRow[Int]](OpDiv) implicit object OpAddDenseVectorRowIntLong extends GeneratedBinaryOp[DenseVectorRow[Int],Long,OpAdd,DenseVectorRow[Long]](OpAdd) implicit object OpSubDenseVectorRowIntLong extends GeneratedBinaryOp[DenseVectorRow[Int],Long,OpSub,DenseVectorRow[Long]](OpSub) implicit object OpMulDenseVectorRowIntLong extends GeneratedBinaryOp[DenseVectorRow[Int],Long,OpMul,DenseVectorRow[Long]](OpMul) implicit object OpDivDenseVectorRowIntLong extends GeneratedBinaryOp[DenseVectorRow[Int],Long,OpDiv,DenseVectorRow[Long]](OpDiv) implicit object OpAddDenseVectorRowIntFloat extends GeneratedBinaryOp[DenseVectorRow[Int],Float,OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubDenseVectorRowIntFloat extends GeneratedBinaryOp[DenseVectorRow[Int],Float,OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulDenseVectorRowIntFloat extends GeneratedBinaryOp[DenseVectorRow[Int],Float,OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivDenseVectorRowIntFloat extends GeneratedBinaryOp[DenseVectorRow[Int],Float,OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddDenseVectorRowIntDouble extends GeneratedBinaryOp[DenseVectorRow[Int],Double,OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDenseVectorRowIntDouble extends GeneratedBinaryOp[DenseVectorRow[Int],Double,OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDenseVectorRowIntDouble extends GeneratedBinaryOp[DenseVectorRow[Int],Double,OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDenseVectorRowIntDouble extends GeneratedBinaryOp[DenseVectorRow[Int],Double,OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDenseVectorRowLongInt extends GeneratedBinaryOp[DenseVectorRow[Long],Int,OpAdd,DenseVectorRow[Long]](OpAdd) implicit object OpSubDenseVectorRowLongInt extends GeneratedBinaryOp[DenseVectorRow[Long],Int,OpSub,DenseVectorRow[Long]](OpSub) implicit object OpMulDenseVectorRowLongInt extends GeneratedBinaryOp[DenseVectorRow[Long],Int,OpMul,DenseVectorRow[Long]](OpMul) implicit object OpDivDenseVectorRowLongInt extends GeneratedBinaryOp[DenseVectorRow[Long],Int,OpDiv,DenseVectorRow[Long]](OpDiv) implicit object OpAddDenseVectorRowLongLong extends GeneratedBinaryOp[DenseVectorRow[Long],Long,OpAdd,DenseVectorRow[Long]](OpAdd) implicit object OpSubDenseVectorRowLongLong extends GeneratedBinaryOp[DenseVectorRow[Long],Long,OpSub,DenseVectorRow[Long]](OpSub) implicit object OpMulDenseVectorRowLongLong extends GeneratedBinaryOp[DenseVectorRow[Long],Long,OpMul,DenseVectorRow[Long]](OpMul) implicit object OpDivDenseVectorRowLongLong extends GeneratedBinaryOp[DenseVectorRow[Long],Long,OpDiv,DenseVectorRow[Long]](OpDiv) implicit object OpAddDenseVectorRowLongFloat extends GeneratedBinaryOp[DenseVectorRow[Long],Float,OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubDenseVectorRowLongFloat extends GeneratedBinaryOp[DenseVectorRow[Long],Float,OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulDenseVectorRowLongFloat extends GeneratedBinaryOp[DenseVectorRow[Long],Float,OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivDenseVectorRowLongFloat extends GeneratedBinaryOp[DenseVectorRow[Long],Float,OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddDenseVectorRowLongDouble extends GeneratedBinaryOp[DenseVectorRow[Long],Double,OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDenseVectorRowLongDouble extends GeneratedBinaryOp[DenseVectorRow[Long],Double,OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDenseVectorRowLongDouble extends GeneratedBinaryOp[DenseVectorRow[Long],Double,OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDenseVectorRowLongDouble extends GeneratedBinaryOp[DenseVectorRow[Long],Double,OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDenseVectorRowFloatInt extends GeneratedBinaryOp[DenseVectorRow[Float],Int,OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubDenseVectorRowFloatInt extends GeneratedBinaryOp[DenseVectorRow[Float],Int,OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulDenseVectorRowFloatInt extends GeneratedBinaryOp[DenseVectorRow[Float],Int,OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivDenseVectorRowFloatInt extends GeneratedBinaryOp[DenseVectorRow[Float],Int,OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddDenseVectorRowFloatLong extends GeneratedBinaryOp[DenseVectorRow[Float],Long,OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubDenseVectorRowFloatLong extends GeneratedBinaryOp[DenseVectorRow[Float],Long,OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulDenseVectorRowFloatLong extends GeneratedBinaryOp[DenseVectorRow[Float],Long,OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivDenseVectorRowFloatLong extends GeneratedBinaryOp[DenseVectorRow[Float],Long,OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddDenseVectorRowFloatFloat extends GeneratedBinaryOp[DenseVectorRow[Float],Float,OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubDenseVectorRowFloatFloat extends GeneratedBinaryOp[DenseVectorRow[Float],Float,OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulDenseVectorRowFloatFloat extends GeneratedBinaryOp[DenseVectorRow[Float],Float,OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivDenseVectorRowFloatFloat extends GeneratedBinaryOp[DenseVectorRow[Float],Float,OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddDenseVectorRowFloatDouble extends GeneratedBinaryOp[DenseVectorRow[Float],Double,OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDenseVectorRowFloatDouble extends GeneratedBinaryOp[DenseVectorRow[Float],Double,OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDenseVectorRowFloatDouble extends GeneratedBinaryOp[DenseVectorRow[Float],Double,OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDenseVectorRowFloatDouble extends GeneratedBinaryOp[DenseVectorRow[Float],Double,OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDenseVectorRowDoubleInt extends GeneratedBinaryOp[DenseVectorRow[Double],Int,OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDenseVectorRowDoubleInt extends GeneratedBinaryOp[DenseVectorRow[Double],Int,OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDenseVectorRowDoubleInt extends GeneratedBinaryOp[DenseVectorRow[Double],Int,OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDenseVectorRowDoubleInt extends GeneratedBinaryOp[DenseVectorRow[Double],Int,OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDenseVectorRowDoubleLong extends GeneratedBinaryOp[DenseVectorRow[Double],Long,OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDenseVectorRowDoubleLong extends GeneratedBinaryOp[DenseVectorRow[Double],Long,OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDenseVectorRowDoubleLong extends GeneratedBinaryOp[DenseVectorRow[Double],Long,OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDenseVectorRowDoubleLong extends GeneratedBinaryOp[DenseVectorRow[Double],Long,OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDenseVectorRowDoubleFloat extends GeneratedBinaryOp[DenseVectorRow[Double],Float,OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDenseVectorRowDoubleFloat extends GeneratedBinaryOp[DenseVectorRow[Double],Float,OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDenseVectorRowDoubleFloat extends GeneratedBinaryOp[DenseVectorRow[Double],Float,OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDenseVectorRowDoubleFloat extends GeneratedBinaryOp[DenseVectorRow[Double],Float,OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDenseVectorRowDoubleDouble extends GeneratedBinaryOp[DenseVectorRow[Double],Double,OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDenseVectorRowDoubleDouble extends GeneratedBinaryOp[DenseVectorRow[Double],Double,OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDenseVectorRowDoubleDouble extends GeneratedBinaryOp[DenseVectorRow[Double],Double,OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDenseVectorRowDoubleDouble extends GeneratedBinaryOp[DenseVectorRow[Double],Double,OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDenseVectorColIntInt extends GeneratedBinaryOp[DenseVectorCol[Int],Int,OpAdd,DenseVectorCol[Int]](OpAdd) implicit object OpSubDenseVectorColIntInt extends GeneratedBinaryOp[DenseVectorCol[Int],Int,OpSub,DenseVectorCol[Int]](OpSub) implicit object OpMulDenseVectorColIntInt extends GeneratedBinaryOp[DenseVectorCol[Int],Int,OpMul,DenseVectorCol[Int]](OpMul) implicit object OpDivDenseVectorColIntInt extends GeneratedBinaryOp[DenseVectorCol[Int],Int,OpDiv,DenseVectorCol[Int]](OpDiv) implicit object OpAddDenseVectorColIntLong extends GeneratedBinaryOp[DenseVectorCol[Int],Long,OpAdd,DenseVectorCol[Long]](OpAdd) implicit object OpSubDenseVectorColIntLong extends GeneratedBinaryOp[DenseVectorCol[Int],Long,OpSub,DenseVectorCol[Long]](OpSub) implicit object OpMulDenseVectorColIntLong extends GeneratedBinaryOp[DenseVectorCol[Int],Long,OpMul,DenseVectorCol[Long]](OpMul) implicit object OpDivDenseVectorColIntLong extends GeneratedBinaryOp[DenseVectorCol[Int],Long,OpDiv,DenseVectorCol[Long]](OpDiv) implicit object OpAddDenseVectorColIntFloat extends GeneratedBinaryOp[DenseVectorCol[Int],Float,OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubDenseVectorColIntFloat extends GeneratedBinaryOp[DenseVectorCol[Int],Float,OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulDenseVectorColIntFloat extends GeneratedBinaryOp[DenseVectorCol[Int],Float,OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivDenseVectorColIntFloat extends GeneratedBinaryOp[DenseVectorCol[Int],Float,OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddDenseVectorColIntDouble extends GeneratedBinaryOp[DenseVectorCol[Int],Double,OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDenseVectorColIntDouble extends GeneratedBinaryOp[DenseVectorCol[Int],Double,OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDenseVectorColIntDouble extends GeneratedBinaryOp[DenseVectorCol[Int],Double,OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDenseVectorColIntDouble extends GeneratedBinaryOp[DenseVectorCol[Int],Double,OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDenseVectorColLongInt extends GeneratedBinaryOp[DenseVectorCol[Long],Int,OpAdd,DenseVectorCol[Long]](OpAdd) implicit object OpSubDenseVectorColLongInt extends GeneratedBinaryOp[DenseVectorCol[Long],Int,OpSub,DenseVectorCol[Long]](OpSub) implicit object OpMulDenseVectorColLongInt extends GeneratedBinaryOp[DenseVectorCol[Long],Int,OpMul,DenseVectorCol[Long]](OpMul) implicit object OpDivDenseVectorColLongInt extends GeneratedBinaryOp[DenseVectorCol[Long],Int,OpDiv,DenseVectorCol[Long]](OpDiv) implicit object OpAddDenseVectorColLongLong extends GeneratedBinaryOp[DenseVectorCol[Long],Long,OpAdd,DenseVectorCol[Long]](OpAdd) implicit object OpSubDenseVectorColLongLong extends GeneratedBinaryOp[DenseVectorCol[Long],Long,OpSub,DenseVectorCol[Long]](OpSub) implicit object OpMulDenseVectorColLongLong extends GeneratedBinaryOp[DenseVectorCol[Long],Long,OpMul,DenseVectorCol[Long]](OpMul) implicit object OpDivDenseVectorColLongLong extends GeneratedBinaryOp[DenseVectorCol[Long],Long,OpDiv,DenseVectorCol[Long]](OpDiv) implicit object OpAddDenseVectorColLongFloat extends GeneratedBinaryOp[DenseVectorCol[Long],Float,OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubDenseVectorColLongFloat extends GeneratedBinaryOp[DenseVectorCol[Long],Float,OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulDenseVectorColLongFloat extends GeneratedBinaryOp[DenseVectorCol[Long],Float,OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivDenseVectorColLongFloat extends GeneratedBinaryOp[DenseVectorCol[Long],Float,OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddDenseVectorColLongDouble extends GeneratedBinaryOp[DenseVectorCol[Long],Double,OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDenseVectorColLongDouble extends GeneratedBinaryOp[DenseVectorCol[Long],Double,OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDenseVectorColLongDouble extends GeneratedBinaryOp[DenseVectorCol[Long],Double,OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDenseVectorColLongDouble extends GeneratedBinaryOp[DenseVectorCol[Long],Double,OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDenseVectorColFloatInt extends GeneratedBinaryOp[DenseVectorCol[Float],Int,OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubDenseVectorColFloatInt extends GeneratedBinaryOp[DenseVectorCol[Float],Int,OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulDenseVectorColFloatInt extends GeneratedBinaryOp[DenseVectorCol[Float],Int,OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivDenseVectorColFloatInt extends GeneratedBinaryOp[DenseVectorCol[Float],Int,OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddDenseVectorColFloatLong extends GeneratedBinaryOp[DenseVectorCol[Float],Long,OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubDenseVectorColFloatLong extends GeneratedBinaryOp[DenseVectorCol[Float],Long,OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulDenseVectorColFloatLong extends GeneratedBinaryOp[DenseVectorCol[Float],Long,OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivDenseVectorColFloatLong extends GeneratedBinaryOp[DenseVectorCol[Float],Long,OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddDenseVectorColFloatFloat extends GeneratedBinaryOp[DenseVectorCol[Float],Float,OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubDenseVectorColFloatFloat extends GeneratedBinaryOp[DenseVectorCol[Float],Float,OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulDenseVectorColFloatFloat extends GeneratedBinaryOp[DenseVectorCol[Float],Float,OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivDenseVectorColFloatFloat extends GeneratedBinaryOp[DenseVectorCol[Float],Float,OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddDenseVectorColFloatDouble extends GeneratedBinaryOp[DenseVectorCol[Float],Double,OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDenseVectorColFloatDouble extends GeneratedBinaryOp[DenseVectorCol[Float],Double,OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDenseVectorColFloatDouble extends GeneratedBinaryOp[DenseVectorCol[Float],Double,OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDenseVectorColFloatDouble extends GeneratedBinaryOp[DenseVectorCol[Float],Double,OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDenseVectorColDoubleInt extends GeneratedBinaryOp[DenseVectorCol[Double],Int,OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDenseVectorColDoubleInt extends GeneratedBinaryOp[DenseVectorCol[Double],Int,OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDenseVectorColDoubleInt extends GeneratedBinaryOp[DenseVectorCol[Double],Int,OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDenseVectorColDoubleInt extends GeneratedBinaryOp[DenseVectorCol[Double],Int,OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDenseVectorColDoubleLong extends GeneratedBinaryOp[DenseVectorCol[Double],Long,OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDenseVectorColDoubleLong extends GeneratedBinaryOp[DenseVectorCol[Double],Long,OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDenseVectorColDoubleLong extends GeneratedBinaryOp[DenseVectorCol[Double],Long,OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDenseVectorColDoubleLong extends GeneratedBinaryOp[DenseVectorCol[Double],Long,OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDenseVectorColDoubleFloat extends GeneratedBinaryOp[DenseVectorCol[Double],Float,OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDenseVectorColDoubleFloat extends GeneratedBinaryOp[DenseVectorCol[Double],Float,OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDenseVectorColDoubleFloat extends GeneratedBinaryOp[DenseVectorCol[Double],Float,OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDenseVectorColDoubleFloat extends GeneratedBinaryOp[DenseVectorCol[Double],Float,OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDenseVectorColDoubleDouble extends GeneratedBinaryOp[DenseVectorCol[Double],Double,OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDenseVectorColDoubleDouble extends GeneratedBinaryOp[DenseVectorCol[Double],Double,OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDenseVectorColDoubleDouble extends GeneratedBinaryOp[DenseVectorCol[Double],Double,OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDenseVectorColDoubleDouble extends GeneratedBinaryOp[DenseVectorCol[Double],Double,OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddIntArrayInt extends GeneratedBinaryOp[Int,Array[Int],OpAdd,Array[Int]](OpAdd) implicit object OpSubIntArrayInt extends GeneratedBinaryOp[Int,Array[Int],OpSub,Array[Int]](OpSub) implicit object OpMulIntArrayInt extends GeneratedBinaryOp[Int,Array[Int],OpMul,Array[Int]](OpMul) implicit object OpDivIntArrayInt extends GeneratedBinaryOp[Int,Array[Int],OpDiv,Array[Int]](OpDiv) implicit object OpAddIntArrayLong extends GeneratedBinaryOp[Int,Array[Long],OpAdd,Array[Long]](OpAdd) implicit object OpSubIntArrayLong extends GeneratedBinaryOp[Int,Array[Long],OpSub,Array[Long]](OpSub) implicit object OpMulIntArrayLong extends GeneratedBinaryOp[Int,Array[Long],OpMul,Array[Long]](OpMul) implicit object OpDivIntArrayLong extends GeneratedBinaryOp[Int,Array[Long],OpDiv,Array[Long]](OpDiv) implicit object OpAddIntArrayFloat extends GeneratedBinaryOp[Int,Array[Float],OpAdd,Array[Float]](OpAdd) implicit object OpSubIntArrayFloat extends GeneratedBinaryOp[Int,Array[Float],OpSub,Array[Float]](OpSub) implicit object OpMulIntArrayFloat extends GeneratedBinaryOp[Int,Array[Float],OpMul,Array[Float]](OpMul) implicit object OpDivIntArrayFloat extends GeneratedBinaryOp[Int,Array[Float],OpDiv,Array[Float]](OpDiv) implicit object OpAddIntArrayDouble extends GeneratedBinaryOp[Int,Array[Double],OpAdd,Array[Double]](OpAdd) implicit object OpSubIntArrayDouble extends GeneratedBinaryOp[Int,Array[Double],OpSub,Array[Double]](OpSub) implicit object OpMulIntArrayDouble extends GeneratedBinaryOp[Int,Array[Double],OpMul,Array[Double]](OpMul) implicit object OpDivIntArrayDouble extends GeneratedBinaryOp[Int,Array[Double],OpDiv,Array[Double]](OpDiv) implicit object OpAddLongArrayInt extends GeneratedBinaryOp[Long,Array[Int],OpAdd,Array[Long]](OpAdd) implicit object OpSubLongArrayInt extends GeneratedBinaryOp[Long,Array[Int],OpSub,Array[Long]](OpSub) implicit object OpMulLongArrayInt extends GeneratedBinaryOp[Long,Array[Int],OpMul,Array[Long]](OpMul) implicit object OpDivLongArrayInt extends GeneratedBinaryOp[Long,Array[Int],OpDiv,Array[Long]](OpDiv) implicit object OpAddLongArrayLong extends GeneratedBinaryOp[Long,Array[Long],OpAdd,Array[Long]](OpAdd) implicit object OpSubLongArrayLong extends GeneratedBinaryOp[Long,Array[Long],OpSub,Array[Long]](OpSub) implicit object OpMulLongArrayLong extends GeneratedBinaryOp[Long,Array[Long],OpMul,Array[Long]](OpMul) implicit object OpDivLongArrayLong extends GeneratedBinaryOp[Long,Array[Long],OpDiv,Array[Long]](OpDiv) implicit object OpAddLongArrayFloat extends GeneratedBinaryOp[Long,Array[Float],OpAdd,Array[Float]](OpAdd) implicit object OpSubLongArrayFloat extends GeneratedBinaryOp[Long,Array[Float],OpSub,Array[Float]](OpSub) implicit object OpMulLongArrayFloat extends GeneratedBinaryOp[Long,Array[Float],OpMul,Array[Float]](OpMul) implicit object OpDivLongArrayFloat extends GeneratedBinaryOp[Long,Array[Float],OpDiv,Array[Float]](OpDiv) implicit object OpAddLongArrayDouble extends GeneratedBinaryOp[Long,Array[Double],OpAdd,Array[Double]](OpAdd) implicit object OpSubLongArrayDouble extends GeneratedBinaryOp[Long,Array[Double],OpSub,Array[Double]](OpSub) implicit object OpMulLongArrayDouble extends GeneratedBinaryOp[Long,Array[Double],OpMul,Array[Double]](OpMul) implicit object OpDivLongArrayDouble extends GeneratedBinaryOp[Long,Array[Double],OpDiv,Array[Double]](OpDiv) implicit object OpAddFloatArrayInt extends GeneratedBinaryOp[Float,Array[Int],OpAdd,Array[Float]](OpAdd) implicit object OpSubFloatArrayInt extends GeneratedBinaryOp[Float,Array[Int],OpSub,Array[Float]](OpSub) implicit object OpMulFloatArrayInt extends GeneratedBinaryOp[Float,Array[Int],OpMul,Array[Float]](OpMul) implicit object OpDivFloatArrayInt extends GeneratedBinaryOp[Float,Array[Int],OpDiv,Array[Float]](OpDiv) implicit object OpAddFloatArrayLong extends GeneratedBinaryOp[Float,Array[Long],OpAdd,Array[Float]](OpAdd) implicit object OpSubFloatArrayLong extends GeneratedBinaryOp[Float,Array[Long],OpSub,Array[Float]](OpSub) implicit object OpMulFloatArrayLong extends GeneratedBinaryOp[Float,Array[Long],OpMul,Array[Float]](OpMul) implicit object OpDivFloatArrayLong extends GeneratedBinaryOp[Float,Array[Long],OpDiv,Array[Float]](OpDiv) implicit object OpAddFloatArrayFloat extends GeneratedBinaryOp[Float,Array[Float],OpAdd,Array[Float]](OpAdd) implicit object OpSubFloatArrayFloat extends GeneratedBinaryOp[Float,Array[Float],OpSub,Array[Float]](OpSub) implicit object OpMulFloatArrayFloat extends GeneratedBinaryOp[Float,Array[Float],OpMul,Array[Float]](OpMul) implicit object OpDivFloatArrayFloat extends GeneratedBinaryOp[Float,Array[Float],OpDiv,Array[Float]](OpDiv) implicit object OpAddFloatArrayDouble extends GeneratedBinaryOp[Float,Array[Double],OpAdd,Array[Double]](OpAdd) implicit object OpSubFloatArrayDouble extends GeneratedBinaryOp[Float,Array[Double],OpSub,Array[Double]](OpSub) implicit object OpMulFloatArrayDouble extends GeneratedBinaryOp[Float,Array[Double],OpMul,Array[Double]](OpMul) implicit object OpDivFloatArrayDouble extends GeneratedBinaryOp[Float,Array[Double],OpDiv,Array[Double]](OpDiv) implicit object OpAddDoubleArrayInt extends GeneratedBinaryOp[Double,Array[Int],OpAdd,Array[Double]](OpAdd) implicit object OpSubDoubleArrayInt extends GeneratedBinaryOp[Double,Array[Int],OpSub,Array[Double]](OpSub) implicit object OpMulDoubleArrayInt extends GeneratedBinaryOp[Double,Array[Int],OpMul,Array[Double]](OpMul) implicit object OpDivDoubleArrayInt extends GeneratedBinaryOp[Double,Array[Int],OpDiv,Array[Double]](OpDiv) implicit object OpAddDoubleArrayLong extends GeneratedBinaryOp[Double,Array[Long],OpAdd,Array[Double]](OpAdd) implicit object OpSubDoubleArrayLong extends GeneratedBinaryOp[Double,Array[Long],OpSub,Array[Double]](OpSub) implicit object OpMulDoubleArrayLong extends GeneratedBinaryOp[Double,Array[Long],OpMul,Array[Double]](OpMul) implicit object OpDivDoubleArrayLong extends GeneratedBinaryOp[Double,Array[Long],OpDiv,Array[Double]](OpDiv) implicit object OpAddDoubleArrayFloat extends GeneratedBinaryOp[Double,Array[Float],OpAdd,Array[Double]](OpAdd) implicit object OpSubDoubleArrayFloat extends GeneratedBinaryOp[Double,Array[Float],OpSub,Array[Double]](OpSub) implicit object OpMulDoubleArrayFloat extends GeneratedBinaryOp[Double,Array[Float],OpMul,Array[Double]](OpMul) implicit object OpDivDoubleArrayFloat extends GeneratedBinaryOp[Double,Array[Float],OpDiv,Array[Double]](OpDiv) implicit object OpAddDoubleArrayDouble extends GeneratedBinaryOp[Double,Array[Double],OpAdd,Array[Double]](OpAdd) implicit object OpSubDoubleArrayDouble extends GeneratedBinaryOp[Double,Array[Double],OpSub,Array[Double]](OpSub) implicit object OpMulDoubleArrayDouble extends GeneratedBinaryOp[Double,Array[Double],OpMul,Array[Double]](OpMul) implicit object OpDivDoubleArrayDouble extends GeneratedBinaryOp[Double,Array[Double],OpDiv,Array[Double]](OpDiv) implicit object OpAddIntDenseVectorRowInt extends GeneratedBinaryOp[Int,DenseVectorRow[Int],OpAdd,DenseVectorRow[Int]](OpAdd) implicit object OpSubIntDenseVectorRowInt extends GeneratedBinaryOp[Int,DenseVectorRow[Int],OpSub,DenseVectorRow[Int]](OpSub) implicit object OpMulIntDenseVectorRowInt extends GeneratedBinaryOp[Int,DenseVectorRow[Int],OpMul,DenseVectorRow[Int]](OpMul) implicit object OpDivIntDenseVectorRowInt extends GeneratedBinaryOp[Int,DenseVectorRow[Int],OpDiv,DenseVectorRow[Int]](OpDiv) implicit object OpAddIntDenseVectorRowLong extends GeneratedBinaryOp[Int,DenseVectorRow[Long],OpAdd,DenseVectorRow[Long]](OpAdd) implicit object OpSubIntDenseVectorRowLong extends GeneratedBinaryOp[Int,DenseVectorRow[Long],OpSub,DenseVectorRow[Long]](OpSub) implicit object OpMulIntDenseVectorRowLong extends GeneratedBinaryOp[Int,DenseVectorRow[Long],OpMul,DenseVectorRow[Long]](OpMul) implicit object OpDivIntDenseVectorRowLong extends GeneratedBinaryOp[Int,DenseVectorRow[Long],OpDiv,DenseVectorRow[Long]](OpDiv) implicit object OpAddIntDenseVectorRowFloat extends GeneratedBinaryOp[Int,DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubIntDenseVectorRowFloat extends GeneratedBinaryOp[Int,DenseVectorRow[Float],OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulIntDenseVectorRowFloat extends GeneratedBinaryOp[Int,DenseVectorRow[Float],OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivIntDenseVectorRowFloat extends GeneratedBinaryOp[Int,DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddIntDenseVectorRowDouble extends GeneratedBinaryOp[Int,DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubIntDenseVectorRowDouble extends GeneratedBinaryOp[Int,DenseVectorRow[Double],OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulIntDenseVectorRowDouble extends GeneratedBinaryOp[Int,DenseVectorRow[Double],OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivIntDenseVectorRowDouble extends GeneratedBinaryOp[Int,DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddLongDenseVectorRowInt extends GeneratedBinaryOp[Long,DenseVectorRow[Int],OpAdd,DenseVectorRow[Long]](OpAdd) implicit object OpSubLongDenseVectorRowInt extends GeneratedBinaryOp[Long,DenseVectorRow[Int],OpSub,DenseVectorRow[Long]](OpSub) implicit object OpMulLongDenseVectorRowInt extends GeneratedBinaryOp[Long,DenseVectorRow[Int],OpMul,DenseVectorRow[Long]](OpMul) implicit object OpDivLongDenseVectorRowInt extends GeneratedBinaryOp[Long,DenseVectorRow[Int],OpDiv,DenseVectorRow[Long]](OpDiv) implicit object OpAddLongDenseVectorRowLong extends GeneratedBinaryOp[Long,DenseVectorRow[Long],OpAdd,DenseVectorRow[Long]](OpAdd) implicit object OpSubLongDenseVectorRowLong extends GeneratedBinaryOp[Long,DenseVectorRow[Long],OpSub,DenseVectorRow[Long]](OpSub) implicit object OpMulLongDenseVectorRowLong extends GeneratedBinaryOp[Long,DenseVectorRow[Long],OpMul,DenseVectorRow[Long]](OpMul) implicit object OpDivLongDenseVectorRowLong extends GeneratedBinaryOp[Long,DenseVectorRow[Long],OpDiv,DenseVectorRow[Long]](OpDiv) implicit object OpAddLongDenseVectorRowFloat extends GeneratedBinaryOp[Long,DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubLongDenseVectorRowFloat extends GeneratedBinaryOp[Long,DenseVectorRow[Float],OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulLongDenseVectorRowFloat extends GeneratedBinaryOp[Long,DenseVectorRow[Float],OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivLongDenseVectorRowFloat extends GeneratedBinaryOp[Long,DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddLongDenseVectorRowDouble extends GeneratedBinaryOp[Long,DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubLongDenseVectorRowDouble extends GeneratedBinaryOp[Long,DenseVectorRow[Double],OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulLongDenseVectorRowDouble extends GeneratedBinaryOp[Long,DenseVectorRow[Double],OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivLongDenseVectorRowDouble extends GeneratedBinaryOp[Long,DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddFloatDenseVectorRowInt extends GeneratedBinaryOp[Float,DenseVectorRow[Int],OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubFloatDenseVectorRowInt extends GeneratedBinaryOp[Float,DenseVectorRow[Int],OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulFloatDenseVectorRowInt extends GeneratedBinaryOp[Float,DenseVectorRow[Int],OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivFloatDenseVectorRowInt extends GeneratedBinaryOp[Float,DenseVectorRow[Int],OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddFloatDenseVectorRowLong extends GeneratedBinaryOp[Float,DenseVectorRow[Long],OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubFloatDenseVectorRowLong extends GeneratedBinaryOp[Float,DenseVectorRow[Long],OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulFloatDenseVectorRowLong extends GeneratedBinaryOp[Float,DenseVectorRow[Long],OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivFloatDenseVectorRowLong extends GeneratedBinaryOp[Float,DenseVectorRow[Long],OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddFloatDenseVectorRowFloat extends GeneratedBinaryOp[Float,DenseVectorRow[Float],OpAdd,DenseVectorRow[Float]](OpAdd) implicit object OpSubFloatDenseVectorRowFloat extends GeneratedBinaryOp[Float,DenseVectorRow[Float],OpSub,DenseVectorRow[Float]](OpSub) implicit object OpMulFloatDenseVectorRowFloat extends GeneratedBinaryOp[Float,DenseVectorRow[Float],OpMul,DenseVectorRow[Float]](OpMul) implicit object OpDivFloatDenseVectorRowFloat extends GeneratedBinaryOp[Float,DenseVectorRow[Float],OpDiv,DenseVectorRow[Float]](OpDiv) implicit object OpAddFloatDenseVectorRowDouble extends GeneratedBinaryOp[Float,DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubFloatDenseVectorRowDouble extends GeneratedBinaryOp[Float,DenseVectorRow[Double],OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulFloatDenseVectorRowDouble extends GeneratedBinaryOp[Float,DenseVectorRow[Double],OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivFloatDenseVectorRowDouble extends GeneratedBinaryOp[Float,DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDoubleDenseVectorRowInt extends GeneratedBinaryOp[Double,DenseVectorRow[Int],OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDoubleDenseVectorRowInt extends GeneratedBinaryOp[Double,DenseVectorRow[Int],OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDoubleDenseVectorRowInt extends GeneratedBinaryOp[Double,DenseVectorRow[Int],OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDoubleDenseVectorRowInt extends GeneratedBinaryOp[Double,DenseVectorRow[Int],OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDoubleDenseVectorRowLong extends GeneratedBinaryOp[Double,DenseVectorRow[Long],OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDoubleDenseVectorRowLong extends GeneratedBinaryOp[Double,DenseVectorRow[Long],OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDoubleDenseVectorRowLong extends GeneratedBinaryOp[Double,DenseVectorRow[Long],OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDoubleDenseVectorRowLong extends GeneratedBinaryOp[Double,DenseVectorRow[Long],OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDoubleDenseVectorRowFloat extends GeneratedBinaryOp[Double,DenseVectorRow[Float],OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDoubleDenseVectorRowFloat extends GeneratedBinaryOp[Double,DenseVectorRow[Float],OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDoubleDenseVectorRowFloat extends GeneratedBinaryOp[Double,DenseVectorRow[Float],OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDoubleDenseVectorRowFloat extends GeneratedBinaryOp[Double,DenseVectorRow[Float],OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddDoubleDenseVectorRowDouble extends GeneratedBinaryOp[Double,DenseVectorRow[Double],OpAdd,DenseVectorRow[Double]](OpAdd) implicit object OpSubDoubleDenseVectorRowDouble extends GeneratedBinaryOp[Double,DenseVectorRow[Double],OpSub,DenseVectorRow[Double]](OpSub) implicit object OpMulDoubleDenseVectorRowDouble extends GeneratedBinaryOp[Double,DenseVectorRow[Double],OpMul,DenseVectorRow[Double]](OpMul) implicit object OpDivDoubleDenseVectorRowDouble extends GeneratedBinaryOp[Double,DenseVectorRow[Double],OpDiv,DenseVectorRow[Double]](OpDiv) implicit object OpAddIntDenseVectorColInt extends GeneratedBinaryOp[Int,DenseVectorCol[Int],OpAdd,DenseVectorCol[Int]](OpAdd) implicit object OpSubIntDenseVectorColInt extends GeneratedBinaryOp[Int,DenseVectorCol[Int],OpSub,DenseVectorCol[Int]](OpSub) implicit object OpMulIntDenseVectorColInt extends GeneratedBinaryOp[Int,DenseVectorCol[Int],OpMul,DenseVectorCol[Int]](OpMul) implicit object OpDivIntDenseVectorColInt extends GeneratedBinaryOp[Int,DenseVectorCol[Int],OpDiv,DenseVectorCol[Int]](OpDiv) implicit object OpAddIntDenseVectorColLong extends GeneratedBinaryOp[Int,DenseVectorCol[Long],OpAdd,DenseVectorCol[Long]](OpAdd) implicit object OpSubIntDenseVectorColLong extends GeneratedBinaryOp[Int,DenseVectorCol[Long],OpSub,DenseVectorCol[Long]](OpSub) implicit object OpMulIntDenseVectorColLong extends GeneratedBinaryOp[Int,DenseVectorCol[Long],OpMul,DenseVectorCol[Long]](OpMul) implicit object OpDivIntDenseVectorColLong extends GeneratedBinaryOp[Int,DenseVectorCol[Long],OpDiv,DenseVectorCol[Long]](OpDiv) implicit object OpAddIntDenseVectorColFloat extends GeneratedBinaryOp[Int,DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubIntDenseVectorColFloat extends GeneratedBinaryOp[Int,DenseVectorCol[Float],OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulIntDenseVectorColFloat extends GeneratedBinaryOp[Int,DenseVectorCol[Float],OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivIntDenseVectorColFloat extends GeneratedBinaryOp[Int,DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddIntDenseVectorColDouble extends GeneratedBinaryOp[Int,DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubIntDenseVectorColDouble extends GeneratedBinaryOp[Int,DenseVectorCol[Double],OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulIntDenseVectorColDouble extends GeneratedBinaryOp[Int,DenseVectorCol[Double],OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivIntDenseVectorColDouble extends GeneratedBinaryOp[Int,DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddLongDenseVectorColInt extends GeneratedBinaryOp[Long,DenseVectorCol[Int],OpAdd,DenseVectorCol[Long]](OpAdd) implicit object OpSubLongDenseVectorColInt extends GeneratedBinaryOp[Long,DenseVectorCol[Int],OpSub,DenseVectorCol[Long]](OpSub) implicit object OpMulLongDenseVectorColInt extends GeneratedBinaryOp[Long,DenseVectorCol[Int],OpMul,DenseVectorCol[Long]](OpMul) implicit object OpDivLongDenseVectorColInt extends GeneratedBinaryOp[Long,DenseVectorCol[Int],OpDiv,DenseVectorCol[Long]](OpDiv) implicit object OpAddLongDenseVectorColLong extends GeneratedBinaryOp[Long,DenseVectorCol[Long],OpAdd,DenseVectorCol[Long]](OpAdd) implicit object OpSubLongDenseVectorColLong extends GeneratedBinaryOp[Long,DenseVectorCol[Long],OpSub,DenseVectorCol[Long]](OpSub) implicit object OpMulLongDenseVectorColLong extends GeneratedBinaryOp[Long,DenseVectorCol[Long],OpMul,DenseVectorCol[Long]](OpMul) implicit object OpDivLongDenseVectorColLong extends GeneratedBinaryOp[Long,DenseVectorCol[Long],OpDiv,DenseVectorCol[Long]](OpDiv) implicit object OpAddLongDenseVectorColFloat extends GeneratedBinaryOp[Long,DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubLongDenseVectorColFloat extends GeneratedBinaryOp[Long,DenseVectorCol[Float],OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulLongDenseVectorColFloat extends GeneratedBinaryOp[Long,DenseVectorCol[Float],OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivLongDenseVectorColFloat extends GeneratedBinaryOp[Long,DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddLongDenseVectorColDouble extends GeneratedBinaryOp[Long,DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubLongDenseVectorColDouble extends GeneratedBinaryOp[Long,DenseVectorCol[Double],OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulLongDenseVectorColDouble extends GeneratedBinaryOp[Long,DenseVectorCol[Double],OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivLongDenseVectorColDouble extends GeneratedBinaryOp[Long,DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddFloatDenseVectorColInt extends GeneratedBinaryOp[Float,DenseVectorCol[Int],OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubFloatDenseVectorColInt extends GeneratedBinaryOp[Float,DenseVectorCol[Int],OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulFloatDenseVectorColInt extends GeneratedBinaryOp[Float,DenseVectorCol[Int],OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivFloatDenseVectorColInt extends GeneratedBinaryOp[Float,DenseVectorCol[Int],OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddFloatDenseVectorColLong extends GeneratedBinaryOp[Float,DenseVectorCol[Long],OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubFloatDenseVectorColLong extends GeneratedBinaryOp[Float,DenseVectorCol[Long],OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulFloatDenseVectorColLong extends GeneratedBinaryOp[Float,DenseVectorCol[Long],OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivFloatDenseVectorColLong extends GeneratedBinaryOp[Float,DenseVectorCol[Long],OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddFloatDenseVectorColFloat extends GeneratedBinaryOp[Float,DenseVectorCol[Float],OpAdd,DenseVectorCol[Float]](OpAdd) implicit object OpSubFloatDenseVectorColFloat extends GeneratedBinaryOp[Float,DenseVectorCol[Float],OpSub,DenseVectorCol[Float]](OpSub) implicit object OpMulFloatDenseVectorColFloat extends GeneratedBinaryOp[Float,DenseVectorCol[Float],OpMul,DenseVectorCol[Float]](OpMul) implicit object OpDivFloatDenseVectorColFloat extends GeneratedBinaryOp[Float,DenseVectorCol[Float],OpDiv,DenseVectorCol[Float]](OpDiv) implicit object OpAddFloatDenseVectorColDouble extends GeneratedBinaryOp[Float,DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubFloatDenseVectorColDouble extends GeneratedBinaryOp[Float,DenseVectorCol[Double],OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulFloatDenseVectorColDouble extends GeneratedBinaryOp[Float,DenseVectorCol[Double],OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivFloatDenseVectorColDouble extends GeneratedBinaryOp[Float,DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDoubleDenseVectorColInt extends GeneratedBinaryOp[Double,DenseVectorCol[Int],OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDoubleDenseVectorColInt extends GeneratedBinaryOp[Double,DenseVectorCol[Int],OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDoubleDenseVectorColInt extends GeneratedBinaryOp[Double,DenseVectorCol[Int],OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDoubleDenseVectorColInt extends GeneratedBinaryOp[Double,DenseVectorCol[Int],OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDoubleDenseVectorColLong extends GeneratedBinaryOp[Double,DenseVectorCol[Long],OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDoubleDenseVectorColLong extends GeneratedBinaryOp[Double,DenseVectorCol[Long],OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDoubleDenseVectorColLong extends GeneratedBinaryOp[Double,DenseVectorCol[Long],OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDoubleDenseVectorColLong extends GeneratedBinaryOp[Double,DenseVectorCol[Long],OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDoubleDenseVectorColFloat extends GeneratedBinaryOp[Double,DenseVectorCol[Float],OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDoubleDenseVectorColFloat extends GeneratedBinaryOp[Double,DenseVectorCol[Float],OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDoubleDenseVectorColFloat extends GeneratedBinaryOp[Double,DenseVectorCol[Float],OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDoubleDenseVectorColFloat extends GeneratedBinaryOp[Double,DenseVectorCol[Float],OpDiv,DenseVectorCol[Double]](OpDiv) implicit object OpAddDoubleDenseVectorColDouble extends GeneratedBinaryOp[Double,DenseVectorCol[Double],OpAdd,DenseVectorCol[Double]](OpAdd) implicit object OpSubDoubleDenseVectorColDouble extends GeneratedBinaryOp[Double,DenseVectorCol[Double],OpSub,DenseVectorCol[Double]](OpSub) implicit object OpMulDoubleDenseVectorColDouble extends GeneratedBinaryOp[Double,DenseVectorCol[Double],OpMul,DenseVectorCol[Double]](OpMul) implicit object OpDivDoubleDenseVectorColDouble extends GeneratedBinaryOp[Double,DenseVectorCol[Double],OpDiv,DenseVectorCol[Double]](OpDiv) } ================================================ FILE: src/main/scala/scalala/scalar/Complex.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package scalar; import scala.math.{ Fractional, Numeric, Ordering }; import scalala.operators._; /** * Immutable complex numbex number representation backed by doubles * for the real and imaginary parts. * * Integration with `scala.math.Numeric` and `scala.math.Fractional` is * provided. * * @author dramage, lancelet */ case class Complex(real : Double, imag : Double) { override def toString = real + " + " + imag + "i"; def +(that : Complex) = Complex(this.real + that.real, this.imag + that.imag); def +(that : Int) = Complex(this.real + that, this.imag); def +(that : Long) = Complex(this.real + that, this.imag); def +(that : Float) = Complex(this.real + that, this.imag); def +(that : Double) = Complex(this.real + that, this.imag); def -(that : Complex) = Complex(this.real - that.real, this.imag - that.imag); def -(that : Int) = Complex(this.real - that, this.imag); def -(that : Long) = Complex(this.real - that, this.imag); def -(that : Float) = Complex(this.real - that, this.imag); def -(that : Double) = Complex(this.real - that, this.imag); def *(that : Complex) = Complex(this.real * that.real - this.imag * that.imag, this.real * that.imag + this.imag * that.real); def *(that : Int) = Complex(this.real * that, this.imag * that); def *(that : Long) = Complex(this.real * that, this.imag * that); def *(that : Float) = Complex(this.real * that, this.imag * that); def *(that : Double) = Complex(this.real * that, this.imag * that); def /(that : Complex) = { val denom = that.real * that.real + that.imag * that.imag; Complex((this.real * that.real + this.imag * that.imag) / denom, (this.imag * that.real - this.real * that.imag) / denom); } def /(that : Int) = Complex(this.real / that, this.imag / that); def /(that : Long) = Complex(this.real / that, this.imag / that); def /(that : Float) = Complex(this.real / that, this.imag / that); def /(that : Double) = Complex(this.real / that, this.imag / that); def unary_- = Complex(-real, -imag); def abs = math.sqrt(real*real + imag*imag); def conjugate = Complex(real, -imag); override def equals(that : Any) = that match { case that : Complex => this.real == that.real && this.imag == that.imag; case real : Double => this.real == real && this.imag == 0; case real : Int => this.real == real && this.imag == 0; case real : Short => this.real == real && this.imag == 0; case real : Long => this.real == real && this.imag == 0; case real : Float => this.real == real && this.imag == 0; case _ => false; } } object Complex { outer => /** Constant Complex(0,0). */ val zero = new Complex(0,0); /** Constant Complex(1,0). */ val one = new Complex(1,0); /** Constant Complex(NaN, NaN). */ val nan = new Complex(Double.NaN, Double.NaN); /** Constant Complex(0,1). */ val i = new Complex(0,1); // // scalar // implicit object scalar extends Scalar[Complex] { def zero = outer.zero; def one = outer.one; def nan = outer.nan; def ==(a : Complex, b : Complex) = a == b; def !=(a : Complex, b : Complex) = a != b; def >(a : Complex, b : Complex) = (a.real > b.real || (a.real == b.real && a.imag > b.imag)); def >=(a : Complex, b : Complex) = (a.real >= b.real || (a.real == b.real && a.imag >= b.imag)); def <(a : Complex, b : Complex) = (a.real < b.real || (a.real == b.real && a.imag < b.imag)); def <=(a : Complex, b : Complex) = (a.real <= b.real || (a.real == b.real && a.imag <= b.imag)); def +(a : Complex, b : Complex) = a + b; def -(a : Complex, b : Complex) = a - b; def *(a : Complex, b : Complex) = a * b; def /(a : Complex, b : Complex) = a / b; def norm(a : Complex) = a.abs; def toDouble(a : Complex) = throw new UnsupportedOperationException("Cannot automatically convert complex numbers to doubles"); def isNaN(a : Complex) = a.real.isNaN || a.imag.isNaN; val manifest = implicitly[ClassManifest[Complex]]; val defaultArrayValue = implicitly[scalala.collection.sparse.DefaultArrayValue[Complex]]; } implicit object decimal extends ScalarDecimal[Complex,Complex] { def decimal = scalar; } // // neg // implicit object Neg extends UnaryOp[Complex,OpNeg,Complex] { def opType = OpNeg; def apply(v : Complex) = -v; } // // cast // implicit object CastIC extends CanCast[Int,Complex] { def apply(v : Int) = Complex(v,0); } implicit object CastLC extends CanCast[Long,Complex] { def apply(v : Long) = Complex(v,0); } implicit object CastFC extends CanCast[Float,Complex] { def apply(v : Float) = Complex(v,0); } implicit object CastDC extends CanCast[Double,Complex] { def apply(v : Double) = Complex(v,0); } // // add // implicit object AddCC extends BinaryOp[Complex,Complex,OpAdd,Complex] { def opType = OpAdd; def apply(a : Complex, b : Complex) = a + b; } implicit object AddIC extends BinaryOp[Int,Complex,OpAdd,Complex] { def opType = OpAdd; def apply(a : Int, b : Complex) = a + b; } implicit object AddLC extends BinaryOp[Long,Complex,OpAdd,Complex] { def opType = OpAdd; def apply(a : Long, b : Complex) = a + b; } implicit object AddFC extends BinaryOp[Float,Complex,OpAdd,Complex] { def opType = OpAdd; def apply(a : Float, b : Complex) = a + b; } implicit object AddDC extends BinaryOp[Double,Complex,OpAdd,Complex] { def opType = OpAdd; def apply(a : Double, b : Complex) = a + b; } implicit object AddCI extends BinaryOp[Complex,Int,OpAdd,Complex] { def opType = OpAdd; def apply(a : Complex, b : Int) = a + b; } implicit object AddCL extends BinaryOp[Complex,Long,OpAdd,Complex] { def opType = OpAdd; def apply(a : Complex, b : Long) = a + b; } implicit object AddCF extends BinaryOp[Complex,Float,OpAdd,Complex] { def opType = OpAdd; def apply(a : Complex, b : Float) = a + b; } implicit object AddCD extends BinaryOp[Complex,Double,OpAdd,Complex] { def opType = OpAdd; def apply(a : Complex, b : Double) = a + b; } // // sub // implicit object SubCC extends BinaryOp[Complex,Complex,OpSub,Complex] { def opType = OpSub; def apply(a : Complex, b : Complex) = a - b; } implicit object SubIC extends BinaryOp[Int,Complex,OpSub,Complex] { def opType = OpSub; def apply(a : Int, b : Complex) = a - b; } implicit object SubLC extends BinaryOp[Long,Complex,OpSub,Complex] { def opType = OpSub; def apply(a : Long, b : Complex) = a - b; } implicit object SubFC extends BinaryOp[Float,Complex,OpSub,Complex] { def opType = OpSub; def apply(a : Float, b : Complex) = a - b; } implicit object SubDC extends BinaryOp[Double,Complex,OpSub,Complex] { def opType = OpSub; def apply(a : Double, b : Complex) = a - b; } implicit object SubCI extends BinaryOp[Complex,Int,OpSub,Complex] { def opType = OpSub; def apply(a : Complex, b : Int) = a - b; } implicit object SubCL extends BinaryOp[Complex,Long,OpSub,Complex] { def opType = OpSub; def apply(a : Complex, b : Long) = a - b; } implicit object SubCF extends BinaryOp[Complex,Float,OpSub,Complex] { def opType = OpSub; def apply(a : Complex, b : Float) = a - b; } implicit object SubCD extends BinaryOp[Complex,Double,OpSub,Complex] { def opType = OpSub; def apply(a : Complex, b : Double) = a - b; } // // mul // implicit object MulCC extends BinaryOp[Complex,Complex,OpMul,Complex] { def opType = OpMul; def apply(a : Complex, b : Complex) = a * b; } implicit object MulIC extends BinaryOp[Int,Complex,OpMul,Complex] { def opType = OpMul; def apply(a : Int, b : Complex) = a * b; } implicit object MulLC extends BinaryOp[Long,Complex,OpMul,Complex] { def opType = OpMul; def apply(a : Long, b : Complex) = a * b; } implicit object MulFC extends BinaryOp[Float,Complex,OpMul,Complex] { def opType = OpMul; def apply(a : Float, b : Complex) = a * b; } implicit object MulDC extends BinaryOp[Double,Complex,OpMul,Complex] { def opType = OpMul; def apply(a : Double, b : Complex) = a * b; } implicit object MulCI extends BinaryOp[Complex,Int,OpMul,Complex] { def opType = OpMul; def apply(a : Complex, b : Int) = a * b; } implicit object MulCL extends BinaryOp[Complex,Long,OpMul,Complex] { def opType = OpMul; def apply(a : Complex, b : Long) = a * b; } implicit object MulCF extends BinaryOp[Complex,Float,OpMul,Complex] { def opType = OpMul; def apply(a : Complex, b : Float) = a * b; } implicit object MulCD extends BinaryOp[Complex,Double,OpMul,Complex] { def opType = OpMul; def apply(a : Complex, b : Double) = a * b; } // // div // implicit object DivCC extends BinaryOp[Complex,Complex,OpDiv,Complex] { def opType = OpDiv; def apply(a : Complex, b : Complex) = a / b; } implicit object DivIC extends BinaryOp[Int,Complex,OpDiv,Complex] { def opType = OpDiv; def apply(a : Int, b : Complex) = a / b; } implicit object DivLC extends BinaryOp[Long,Complex,OpDiv,Complex] { def opType = OpDiv; def apply(a : Long, b : Complex) = a / b; } implicit object DivFC extends BinaryOp[Float,Complex,OpDiv,Complex] { def opType = OpDiv; def apply(a : Float, b : Complex) = a / b; } implicit object DivDC extends BinaryOp[Double,Complex,OpDiv,Complex] { def opType = OpDiv; def apply(a : Double, b : Complex) = a / b; } implicit object DivCI extends BinaryOp[Complex,Int,OpDiv,Complex] { def opType = OpDiv; def apply(a : Complex, b : Int) = a / b; } implicit object DivCL extends BinaryOp[Complex,Long,OpDiv,Complex] { def opType = OpDiv; def apply(a : Complex, b : Long) = a / b; } implicit object DivCF extends BinaryOp[Complex,Float,OpDiv,Complex] { def opType = OpDiv; def apply(a : Complex, b : Float) = a / b; } implicit object DivCD extends BinaryOp[Complex,Double,OpDiv,Complex] { def opType = OpDiv; def apply(a : Complex, b : Double) = a / b; } // // scala.math.Numeric and scala.math.Fractional // // TODO: Implement scala.math.Integral trait, if this is ever required // for some reason. /** `Complex` as `scala.math.Numeric` trait. * Conversions to `Int`, `Long`, `Float` and `Double` are only performed * if the imaginary component of the complex number is exactly 0. */ trait ComplexIsConflicted extends Numeric[Complex] { def plus(x: Complex, y: Complex): Complex = x + y def minus(x: Complex, y: Complex): Complex = x - y def times(x: Complex, y: Complex): Complex = x * y def negate(x: Complex): Complex = -x def fromInt(x: Int): Complex = Complex(x, 0) def toInt(x: Complex): Int = strictlyReal(x).toInt def toLong(x: Complex): Long = strictlyReal(x).toLong def toFloat(x: Complex): Float = strictlyReal(x).toFloat def toDouble(x: Complex): Double = strictlyReal(x) /** Checks that a `Complex` number is strictly real, and returns the real * component. */ private def strictlyReal(x: Complex): Double = { require(x.imag == 0.0) // only proceed if x.imag is *exactly* zero x.real } } /** `Complex` as `scala.math.Fractional` trait. */ trait ComplexIsFractional extends ComplexIsConflicted with Fractional[Complex] { def div(x: Complex, y: Complex): Complex = x / y } /** Ordering for complex numbers: orders lexicographically first * on the real, then on the imaginary part of the number. */ trait ComplexOrdering extends Ordering[Complex] { override def compare(a : Complex, b : Complex) = { if (a.real < b.real) -1 else if (a.real > b.real) 1 else if (a.imag < b.imag) -1 else if (a.imag > b.imag) 1 else 0; } } /** Implicit object providing `scala.math.Fractional` capabilities. * Although complex numbers have no natural ordering, some kind of * `Ordering` is required because `Numeric` extends `Ordering`. Hence, * an ordering based upon the real then imaginary components is used. */ implicit object ComplexIsFractional extends ComplexIsFractional with ComplexOrdering } ================================================ FILE: src/main/scala/scalala/scalar/RichScalar.scala ================================================ package scalala.scalar class RichScalar(value: Double) { def +(c: Complex): Complex = Complex(value, 0) + c; def -(c: Complex): Complex = Complex(value, 0) - c; def *(c: Complex): Complex = Complex(value, 0) * c; def /(c: Complex): Complex = Complex(value, 0) / c; } ================================================ FILE: src/main/scala/scalala/scalar/Scalar.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package scalar; import scala.annotation.implicitNotFound; import scalala.collection.sparse.DefaultArrayValue; /** * Marker trait for scalar values. Scalars must be immutable. * * @author dramage */ @implicitNotFound(msg="${V} is not a scalar value") trait Scalar[@specialized(Int,Short,Long,Float,Double) V] extends Serializable { def zero : V; def one : V; def nan : V; def ==(a : V, b : V) : Boolean; def !=(a : V, b : V) : Boolean; def >(a : V, b : V) : Boolean; def >=(a : V, b : V) : Boolean; def <(a : V, b : V) : Boolean; def <=(a : V, b : V) : Boolean; def +(a : V, b : V) : V; def -(a : V, b : V) : V; def *(a : V, b : V) : V; def /(a : V, b : V) : V; def min(a : V, b : V) : V = if (<=(a,b)) a else b; def max(a : V, b : V) : V = if (>=(a,b)) a else b; /** Returns true if this is a primitive type. */ def isPrimitive : Boolean = ! (manifest <:< implicitly[Manifest[AnyRef]]); /** Returns the norm of this value, the absolute value as a Double. */ def norm(a : V) : Double; /** Returns this value as a Double. May throw UnsupportedOperationException. */ def toDouble(a : V) : Double; /** Returns true if this is not a number. */ def isNaN(a : V) : Boolean; /** Returns the class manifest of the scalar type. */ def manifest : ClassManifest[V]; /** Returns the DefaultArrayValue for this type. Always this.zero. */ def defaultArrayValue : DefaultArrayValue[V]; } object Scalar { implicit object ScalarI extends Scalar[Int] { def zero = 0; def one = 1; def nan = throw new ArithmeticException("Operation resulted in integer-valued NaN"); def ==(a : Int, b : Int) = a == b; def !=(a : Int, b : Int) = a != b; def >(a : Int, b : Int) = a > b; def >=(a : Int, b : Int) = a >= b; def <(a : Int, b : Int) = a < b; def <=(a : Int, b : Int) = a <= b; def +(a : Int, b : Int) = a + b; def -(a : Int, b : Int) = a - b; def *(a : Int, b : Int) = a * b; def /(a : Int, b : Int) = a / b; def norm(a : Int) = if (a < 0) -a else a; def toDouble(a : Int) = a; def isNaN(a : Int) = false; val manifest = implicitly[ClassManifest[Int]]; val defaultArrayValue = implicitly[DefaultArrayValue[Int]]; } implicit object ScalarS extends Scalar[Short] { def zero = 0.asInstanceOf[Short]; def one = 1.asInstanceOf[Short]; def nan = throw new ArithmeticException("Operation resulted in short-valued NaN"); def ==(a : Short, b : Short) = a == b; def !=(a : Short, b : Short) = a != b; def >(a : Short, b : Short) = a > b; def >=(a : Short, b : Short) = a >= b; def <(a : Short, b : Short) = a < b; def <=(a : Short, b : Short) = a <= b; def +(a : Short, b : Short) = (a + b).asInstanceOf[Short]; def -(a : Short, b : Short) = (a - b).asInstanceOf[Short]; def *(a : Short, b : Short) = (a * b).asInstanceOf[Short]; def /(a : Short, b : Short) = (a / b).asInstanceOf[Short]; def norm(a : Short) = if (a < 0) -a else a; def toDouble(a : Short) = a; def isNaN(a : Short) = false; val manifest = implicitly[ClassManifest[Short]]; val defaultArrayValue = implicitly[DefaultArrayValue[Short]]; } implicit object ScalarL extends Scalar[Long] { def zero = 0l; def one = 1l; def nan = throw new ArithmeticException("Operation resulted in long-valued NaN"); def ==(a : Long, b : Long) = a == b; def !=(a : Long, b : Long) = a != b; def >(a : Long, b : Long) = a > b; def >=(a : Long, b : Long) = a >= b; def <(a : Long, b : Long) = a < b; def <=(a : Long, b : Long) = a <= b; def +(a : Long, b : Long) = a + b; def -(a : Long, b : Long) = a - b; def *(a : Long, b : Long) = a * b; def /(a : Long, b : Long) = a / b; def norm(a : Long) = if (a < 0) -a else a; def toDouble(a : Long) = a; def isNaN(a : Long) = false; val manifest = implicitly[ClassManifest[Long]]; val defaultArrayValue = implicitly[DefaultArrayValue[Long]]; } implicit object scalarF extends Scalar[Float] { def zero = 0.0f; def one = 1.0f; def nan = Float.NaN; def ==(a : Float, b : Float) = a == b; def !=(a : Float, b : Float) = a != b; def >(a : Float, b : Float) = a > b; def >=(a : Float, b : Float) = a >= b; def <(a : Float, b : Float) = a < b; def <=(a : Float, b : Float) = a <= b; def +(a : Float, b : Float) = a + b; def -(a : Float, b : Float) = a - b; def *(a : Float, b : Float) = a * b; def /(a : Float, b : Float) = a / b; def norm(a : Float) = if (a < 0) -a else a; def toDouble(a : Float) = a; def isNaN(a : Float) = java.lang.Float.isNaN(a); val manifest = implicitly[ClassManifest[Float]]; val defaultArrayValue = implicitly[DefaultArrayValue[Float]]; } implicit object scalarD extends Scalar[Double] { def zero = 0.0; def one = 1.0; def nan = Double.NaN; def ==(a : Double, b : Double) = a == b; def !=(a : Double, b : Double) = a != b; def >(a : Double, b : Double) = a > b; def >=(a : Double, b : Double) = a >= b; def <(a : Double, b : Double) = a < b; def <=(a : Double, b : Double) = a <= b; def +(a : Double, b : Double) = a + b; def -(a : Double, b : Double) = a - b; def *(a : Double, b : Double) = a * b; def /(a : Double, b : Double) = a / b; def norm(a : Double) = if (a < 0) -a else a; def toDouble(a : Double) = a; def isNaN(a : Double) = java.lang.Double.isNaN(a); val manifest = implicitly[ClassManifest[Double]]; val defaultArrayValue = implicitly[DefaultArrayValue[Double]]; } implicit object scalarB extends Scalar[Boolean] { def zero = false; def one = true; def nan = throw new ArithmeticException("Operation resulted in boolean-valued NaN"); def ==(a : Boolean, b : Boolean) = a == b; def !=(a : Boolean, b : Boolean) = a != b; def >(a : Boolean, b : Boolean) = a > b; def >=(a : Boolean, b : Boolean) = a >= b; def <(a : Boolean, b : Boolean) = a < b; def <=(a : Boolean, b : Boolean) = a <= b; def +(a : Boolean, b : Boolean) = a || b; def -(a : Boolean, b : Boolean) = throw new UnsupportedOperationException(); def *(a : Boolean, b : Boolean) = a && b; def /(a : Boolean, b : Boolean) = throw new UnsupportedOperationException(); def norm(a : Boolean) = if (a) 1.0 else 0.0; def toDouble(a : Boolean) = if (a) 1.0 else 0.0; def isNaN(a : Boolean) = false; def manifest = implicitly[ClassManifest[Boolean]]; val defaultArrayValue = implicitly[DefaultArrayValue[Boolean]]; } /** The default array value for a scalar is zero. */ implicit def defaultArrayValue[V:Scalar] : DefaultArrayValue[V] = implicitly[Scalar[V]].defaultArrayValue; } ================================================ FILE: src/main/scala/scalala/scalar/ScalarDecimal.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package scalar; import scala.annotation.implicitNotFound; import scalala.collection.sparse.DefaultArrayValue; /** * Get a decimal value for the given scalar type. * * @author dramage */ @implicitNotFound(msg="No decimal defined for ${SV}") trait ScalarDecimal[SV,DV] { def decimal : Scalar[DV]; } object ScalarDecimal { class DefaultScalarDecimal[SV:Scalar,DV:Scalar] extends ScalarDecimal[SV,DV] { def decimal = implicitly[Scalar[DV]]; } implicit object ScalarDecimalBD extends DefaultScalarDecimal[Boolean,Double]; implicit object ScalarDecimalID extends DefaultScalarDecimal[Int,Double]; implicit object ScalarDecimalSD extends DefaultScalarDecimal[Short,Double]; implicit object ScalarDecimalLD extends DefaultScalarDecimal[Long,Double]; implicit object ScalarDecimalFD extends DefaultScalarDecimal[Float,Double]; implicit object ScalarDecimalDD extends DefaultScalarDecimal[Double,Double]; } ================================================ FILE: src/main/scala/scalala/scalar/package.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; /** * Defines i. * * @author dramage */ package object scalar { val i = Complex.i; implicit def richInt(value : Int) = new RichScalar(value); implicit def richLong(value : Long) = new RichScalar(value); implicit def richFloat(value : Float) = new RichScalar(value); implicit def richDouble(value : Double) = new RichScalar(value); } ================================================ FILE: src/main/scala/scalala/tensor/CRSTensor2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain._; import generic.{TensorBuilder,TensorPairsMonadic}; import scalala.scalar.Scalar; import scalala.generic.collection._ import tensor.Counter2.Curried /** * A Tensor2 with an open row key domain that maps to an arbitrary Tensor1 as its rows. * * CRS = Compress Row Storage * * @author dlwh */ trait CRSTensor2Like [K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +M1[VV] <: Curried[scala.collection.Map,K1]#Result[VV], +T <: Tensor1[K2,V], +This<:CRSTensor2[K1,K2,V,T]] extends Tensor2Like[K1,K2,V,SetDomain[K1],SetDomain[K2],Domain2[K1,K2],Domain2[K2,K1],This] { self => protected def k2domain:Domain1[K2]; override def newBuilder[NK,NV:Scalar](domain : IterableDomain[NK]) : TensorBuilder[NK,NV,Tensor[NK,NV]] = domain match { case that : IndexDomain => super.newBuilder(that) case that : Domain1[_] => mutable.Counter(that)(implicitly[Scalar[NV]]).asBuilder; case that : Domain2[_,_] => mutable.Counter2(that)(implicitly[Scalar[NV]]).asBuilder; case _ => super.newBuilder(domain); } def data : M1[_<:T]; def apply(i: K1, j: K2) = data(i)(j); override def size = { var s = 0; for (m <- data.valuesIterator) { s += m.size } s; } override def domain : Domain2[K1,K2] = { new Domain2[K1,K2] { def _1 = new SetDomain(data.keySet) def _2 = k2domain; } } override def checkKey(k : K1, k2: K2) = data(k).checkKey(k2); // TODO: how to implement this nicely? override def checkDomain(d : scalala.tensor.domain.Domain[(K1,K2)]) = (); // // faster implementations // override def foreachKey[U](fn : ((K1,K2)) => U) : Unit = for((k1,m) <- data; k2 <- m.keys) fn(k1->k2); override def foreachValue[U](fn : V => U) : Unit = valuesIterator.foreach(fn); override def foreachTriple[U](fn : (K1,K2,V) => U) : Unit = triplesIterator.foreach(triple => fn(triple._1,triple._2,triple._3)); override def keysIterator = for ((k1,m) <- data.iterator; k2 <- m.keysIterator) yield (k1,k2); override def valuesIterator = for (m <- data.valuesIterator; v <- m.valuesIterator) yield v override def pairsIterator = for ((k1,m) <- data.iterator; (k2,v) <- m.pairsIterator) yield (k1,k2)->v; override def triplesIterator = for ((k1,m) <- data.iterator; (k2,v) <- m.pairsIterator) yield (k1,k2,v); } /** * A Tensor2 with an open row key domain that maps to an arbitrary Tensor1 as its rows. * * CRS = Compress Row Storage * * @author dlwh */ trait CRSTensor2 [K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +T<:Tensor1[K2,V]] extends Tensor2[K1,K2,V] with CRSTensor2Like[K1,K2,V,Curried[scala.collection.Map,K1]#Result,T,CRSTensor2[K1,K2,V,T]]; object CRSTensor2 { /** * Returns a new empty CRSTensor2 using the "template" to create rows. The actual rows are zero'd out versions of * the template. */ def apply[K1,K2,V,T<:mutable.Tensor1[K2,V]](template: T)(implicit view: CanViewAsTensor1[T,K2,V], zeros: CanCreateZerosLike[T,T], scalar: Scalar[V]) : mutable.CRSTensor2[K1,K2,V,T] = mutable.CRSTensor2[K1,K2,V,T](template); implicit def canSliceRow[K1,K2,V,T<:Tensor1[K2,V]] : CanSliceRow[CRSTensor2[K1,K2,V,T],K1,T] = new CanSliceRow[CRSTensor2[K1,K2,V,T],K1,T] { override def apply(from : CRSTensor2[K1,K2,V,T], row : K1) = from.data(row); } } ================================================ FILE: src/main/scala/scalala/tensor/Counter.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain._; import generic.{TensorBuilder,TensorPairsMonadic}; import scalala.scalar.Scalar import scalala.generic.collection._ ; /** * A map-like tensor that acts like a collection of key-value pairs where * the set of values may grow arbitrarily. * * @author dramage */ trait CounterLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +M<:scala.collection.Map[K,V], +This<:Counter[K,V]] extends Tensor1Like[K,V,SetDomain[K],This] { self => override def newBuilder[NK,NV:Scalar](domain : IterableDomain[NK]) : TensorBuilder[NK,NV,Tensor[NK,NV]] = domain match { case that : IndexDomain => super.newBuilder(that) case that : Domain1[_] => mutable.Counter(that)(implicitly[Scalar[NV]]).asBuilder; case _ => super.newBuilder(domain); } def data : M; override def domain : SetDomain[K] = new SetDomain(data.keySet); override def size = data.size; def isEmpty = data.isEmpty def contains(k: K) = data.contains(k); override def apply(k : K) = { data.get(k) getOrElse scalar.zero }; def get(k: K) = data.get(k); override def checkKey(k : K) = (); override def checkDomain(d : scalala.tensor.domain.Domain[K]) = (); // // faster implementations // override def foreachPair[U](fn : (K,V) => U) : Unit = data.foreach(fn.tupled); override def foreachKey[U](fn : K => U) : Unit = data.keysIterator.foreach(fn); override def foreachValue[U](fn : V => U) : Unit = data.valuesIterator.foreach(fn); override def keysIterator = data.keysIterator; override def valuesIterator = data.valuesIterator; override def pairsIterator = data.iterator; } trait Counter [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] extends Tensor1[K,V] with CounterLike[K,V,scala.collection.Map[K,V],Counter[K,V]]; private[scalala] trait CounterRowProxyLike[K,V,+This<:CounterRowProxy[K,V]] extends Tensor1ProxyLike[K,V,Domain1[K],Counter[K,V],This] with Tensor1RowLike[K,V,Domain1[K],This]; private[scalala] trait CounterRowProxy[K,V] extends Tensor1Proxy[K,V,Counter[K,V]] with Tensor1Row[K,V] with CounterRowProxyLike[K,V,CounterRowProxy[K,V]]; private[scalala] trait CounterColProxyLike[K,V,+This<:CounterColProxy[K,V]] extends Tensor1ProxyLike[K,V,Domain1[K],Counter[K,V],This] with Tensor1ColLike[K,V,Domain1[K],This]; private[scalala] trait CounterColProxy[K,V] extends Tensor1Proxy[K,V,Counter[K,V]] with Tensor1Col[K,V] with CounterColProxyLike[K,V,CounterColProxy[K,V]]; trait CounterImplicitsLevel0 { /** View a Counter as a row. */ implicit def counterAsRow[K,V](counter : Counter[K,V]) : Tensor1Row[K,V] = new CounterRowProxy[K,V] { override def inner = counter; } } trait CounterImplicitsLevel1 extends CounterImplicitsLevel0 { /** View a Counter as a column. */ implicit def counterAsCol[K,V](counter : Counter[K,V]) : Tensor1Col[K,V] = new CounterColProxy[K,V] { override def inner = counter; } } object Counter extends CounterImplicitsLevel1 { def apply[K,V:Scalar]() : mutable.Counter[K,V] = mutable.Counter(); def apply[K,V:Scalar](values : (K,V)*) : mutable.Counter[K,V] = mutable.Counter(values :_ *); def apply[K,V:Scalar](values : TraversableOnce[(K,V)]) : mutable.Counter[K,V] = mutable.Counter(values); def apply[K,V:Scalar](domain : Domain1[K]) = mutable.Counter(domain); def count[K](items : TraversableOnce[K]) : mutable.Counter[K,Int] = mutable.Counter.count(items); def count[K](items: K*): mutable.Counter[K,Int] = count(items); implicit def CanMapValuesCounter [@specialized(Int) K, @specialized(Int,Double) V, @specialized(Int,Double) RV:Scalar]: CanMapValues[Counter[K, V], V, RV, Counter[K, RV]] = new CanMapValues[Counter[K,V],V,RV,Counter[K,RV]] { override def map(from : Counter[K,V], fn : (V=>RV)) = { val rv = Counter[K,RV](); for( (k,v) <- from.pairsIterator) { rv(k) = fn(from.data(k)); } rv; } override def mapNonZero(from : Counter[K,V], fn : (V=>RV)) = { val rv = Counter[K,RV](); for( (k,v) <- from.pairsIteratorNonZero) { rv(k) = fn(from.data(k)); } rv; } } } ================================================ FILE: src/main/scala/scalala/tensor/Counter2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain._; import generic.{TensorBuilder,TensorPairsMonadic}; import scalala.scalar.Scalar; import scalala.generic.collection._ import tensor.Counter2.Curried ; /** * A map-like tensor that acts like a collection of key-value pairs where * the set of values may grow arbitrarily. * * @author dlwh */ trait Counter2Like [K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +M1[VV] <: Curried[scala.collection.Map,K1]#Result[VV], +T <: Counter[K2,V], +This<:Counter2[K1,K2,V]] extends Tensor2Like[K1,K2,V,SetDomain[K1],SetDomain[K2],Domain2[K1,K2],Domain2[K2,K1],This] // TODO: this hsould work instead extends CRSTensor2Like[K1,K2,V,M1,T,This] //with TensorPairsMonadic[(K1,K2),V,This] { self => override def newBuilder[NK,NV:Scalar](domain : IterableDomain[NK]) : TensorBuilder[NK,NV,Tensor[NK,NV]] = domain match { case that : IndexDomain => super.newBuilder(that) case that : Domain1[_] => mutable.Counter(that)(implicitly[Scalar[NV]]).asBuilder; case that : Domain2[_,_] => mutable.Counter2(that)(implicitly[Scalar[NV]]).asBuilder; case _ => super.newBuilder(domain); } def data : M1[_<:T]; override def size = { var s = 0; for (m <- data.valuesIterator) { s += m.size } s; } override def domain : Domain2[K1,K2] = { new Domain2[K1,K2] { def _1 = new SetDomain(data.keySet) def _2 = new SetDomain(data.values.flatMap(_.domain).toSet); } } override def apply(k : K1, k2: K2) = data.get(k).map(t => t(k2)) getOrElse scalar.zero; override def checkKey(k : K1, k2: K2) = (); override def checkDomain(d : scalala.tensor.domain.Domain[(K1,K2)]) = (); def contains(k: K1) = data.contains(k); def contains(k1: K1, k2: K2) = data.contains(k1) && data(k1).contains(k2) // // faster implementations // override def foreachKey[U](fn : ((K1,K2)) => U) : Unit = for((k1,m) <- data; k2 <- m.keys) fn(k1->k2); override def foreachValue[U](fn : V => U) : Unit = valuesIterator.foreach(fn); override def foreachTriple[U](fn : (K1,K2,V) => U) : Unit = triplesIterator.foreach(triple => fn(triple._1,triple._2,triple._3)); override def keysIterator = for ((k1,m) <- data.iterator; k2 <- m.keysIterator) yield (k1,k2); override def valuesIterator = for (m <- data.valuesIterator; v <- m.valuesIterator) yield v override def pairsIterator = for ((k1,m) <- data.iterator; (k2,v) <- m.pairsIterator) yield (k1,k2)->v; override def triplesIterator = for ((k1,m) <- data.iterator; (k2,v) <- m.pairsIterator) yield (k1,k2,v); } trait Counter2 [K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V] extends Tensor2[K1,K2,V] with Counter2Like[K1,K2,V,Curried[scala.collection.Map,K1]#Result,Counter[K2,V],Counter2[K1,K2,V]]; object Counter2 { def apply[K1,K2,V:Scalar]() : mutable.Counter2[K1,K2,V] = mutable.Counter2(); def apply[K1,K2,V:Scalar](values : (K1,K2,V)*) : mutable.Counter2[K1,K2,V] = mutable.Counter2(values :_ *); def apply[K1,K2,V:Scalar](values : TraversableOnce[(K1,K2,V)]) : mutable.Counter2[K1,K2,V] = mutable.Counter2(values); def apply[K1,K2,V:Scalar](domain : Domain2[K1,K2]) = mutable.Counter2(domain); def count[K1,K2](items : TraversableOnce[(K1,K2)]) : mutable.Counter2[K1,K2,Int] = mutable.Counter2.count(items); /** * This is just a curried version of scala.collection.Map. * Used to get around Scala's lack of partially applied types. * * @author dlwh */ trait Curried[M[_,_],K] { type Result[V] = M[K,V]; } implicit def canSliceRow[K1,K2,V:Scalar] : CanSliceRow[Counter2[K1,K2,V],K1,Counter[K2,V]] = new CanSliceRow[Counter2[K1,K2,V],K1,Counter[K2,V]] { val vS = implicitly[Scalar[V]]; override def apply(from : Counter2[K1,K2,V], row : K1) = from.data(row); } implicit def canSliceCol[K1,K2,V:Scalar]: CanSliceCol[Counter2[K1,K2,V],K2,Counter[K1,V]] = new CanSliceCol[Counter2[K1,K2,V],K2,Counter[K1,V]] { val vS = implicitly[Scalar[V]]; def apply(from: Counter2[K1, K2, V], col: K2) = new Counter[K1,V] { val scalar = vS; def data = new MapSlice(from.data,col); } } import scala.collection.Map private class MapSlice[K1,K2,V](m: Map[K1,Counter[K2,V]],col: K2) extends Map[K1,V] { def get(key: K1) = m.get(key).flatMap(_.get(col)) def iterator = for( (k,inner) <- m.iterator if inner.contains(col)) yield (k,inner(col)) def +[B1 >: V](kv: (K1, B1)) = Map(kv) ++ this; def -(key: K1) = Map() ++ this - key } // implicit def Counter2CanSolveCounter[K1,K2,V] // extends BinaryOp[Counter2[K1,K2,V],Counter[K2,V],OpSolveMatrixBy,Counter[K1,V]] { // override def opType = OpSolveMatrixBy; // override def apply(A : Counter2[K1,K2,V], V : Counter[K2,V]) = { // val // } } ================================================ FILE: src/main/scala/scalala/tensor/DiagonalMatrix.scala ================================================ package scalala package tensor import domain.TableDomain import scalar.Scalar /** * A matrix with values only on its diagonal, as defined by the * given vector. * * @author dlwh, dramage */ class DiagonalMatrix[Vec,V](val diag : Vec) (implicit val scalar: Scalar[V], view: Vec<:U)) : Boolean = { diag.foreachNonZeroKey((i : Int) => fn((i,i))); false; } override def foreachNonZeroValue[U](fn : (V=>U)) : Boolean = { diag.foreachNonZeroValue(fn); false; } override def foreachNonZeroPair[U](fn : ((Int,Int),V)=>U) : Boolean = { diag.foreachNonZeroPair((i : Int, v : V) => fn((i,i),v)); false; } override def foreachNonZeroTriple[U](fn : (Int,Int,V)=>U) : Boolean = diag.foreachNonZeroPair((i : Int, v : V) => fn(i,i,v)); override def keysIteratorNonZero = diag.keysIteratorNonZero.map(i => (i,i)); override def valuesIteratorNonZero = diag.valuesIteratorNonZero; override def pairsIteratorNonZero = diag.pairsIteratorNonZero.map(tup => ((tup._1,tup._1),tup._2)); override def triplesIteratorNonZero = diag.pairsIteratorNonZero.map(tup => (tup._1, tup._1, tup._2)); } ================================================ FILE: src/main/scala/scalala/tensor/DomainFunction.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain._; /** * A function over a Domain of elements of type A returning values * of type B. This type extends PartialFunction by restricting the * domain of possible input functions to an explicitly represented domain. * * @author dramage */ trait DomainFunction [@specialized(Int,Long,Float,Double) K, @specialized(Int,Long,Float,Double,Boolean) +V, +D <: Domain[K]] extends PartialFunction[K, V] { /** The domain over which this function is defined. */ def domain : D; /** Returns true if the key is in the function's domain. */ override def isDefinedAt(key : K) = domain(key); /** @throws DomainException if key is not in the domain. */ def checkKey(key : K) : Unit = { if (!isDefinedAt(key)) throw new DomainException("Key " + key + " not in domain"); } /** @throws DomainException if domain is not equal to this domain. */ def checkDomain(domain : Domain[K]) : Unit = { if (this.domain != domain) throw new DomainException("Incompatible domain: "+domain + " for " + this.domain); } def apply(key : K) : V; } ================================================ FILE: src/main/scala/scalala/tensor/LiteralRow.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; /** * Marker trait for a row literal used in Matrix construction. * * @author dramage */ trait LiteralRow[-R, @specialized V] { def foreach[X](row : R, fn : ((Int,V) => X)); def length(row : R) : Int; } object LiteralRow { implicit def array[V] : LiteralRow[Array[V],V] = new LiteralRow[Array[V],V] { def foreach[X](arr : Array[V], fn : ((Int,V) => X)) = { for (i <- 0 until arr.length) { fn(i, arr(i)); } } def length(arr : Array[V]) = arr.length; } implicit def row[V] : LiteralRow[VectorRow[V],V] = new LiteralRow[VectorRow[V],V] { def foreach[X](row : VectorRow[V], fn : ((Int,V) => X)) = { row.foreachNonZeroPair(fn); } def length(row : VectorRow[V]) = row.size; } implicit def tuple2[V] : LiteralRow[Tuple2[V,V],V] = new LiteralRow[Tuple2[V,V],V] { def foreach[X](tup : Tuple2[V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); } def length(tup : Tuple2[V,V]) = 2; } implicit def tuple3[V] : LiteralRow[Tuple3[V,V,V],V] = new LiteralRow[Tuple3[V,V,V],V] { def foreach[X](tup : Tuple3[V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); } def length(tup : Tuple3[V,V,V]) = 3; } implicit def tuple4[V] : LiteralRow[Tuple4[V,V,V,V],V] = new LiteralRow[Tuple4[V,V,V,V],V] { def foreach[X](tup : Tuple4[V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); } def length(tup : Tuple4[V,V,V,V]) = 4; } implicit def tuple5[V] : LiteralRow[Tuple5[V,V,V,V,V],V] = new LiteralRow[Tuple5[V,V,V,V,V],V] { def foreach[X](tup : Tuple5[V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); } def length(tup : Tuple5[V,V,V,V,V]) = 5; } implicit def tuple6[V] : LiteralRow[Tuple6[V,V,V,V,V,V],V] = new LiteralRow[Tuple6[V,V,V,V,V,V],V] { def foreach[X](tup : Tuple6[V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); } def length(tup : Tuple6[V,V,V,V,V,V]) = 6; } implicit def tuple7[V] : LiteralRow[Tuple7[V,V,V,V,V,V,V],V] = new LiteralRow[Tuple7[V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple7[V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); } def length(tup : Tuple7[V,V,V,V,V,V,V]) = 7; } implicit def tuple8[V] : LiteralRow[Tuple8[V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple8[V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple8[V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); } def length(tup : Tuple8[V,V,V,V,V,V,V,V]) = 8; } implicit def tuple9[V] : LiteralRow[Tuple9[V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple9[V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple9[V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); } def length(tup : Tuple9[V,V,V,V,V,V,V,V,V]) = 9; } implicit def tuple10[V] : LiteralRow[Tuple10[V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple10[V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple10[V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); } def length(tup : Tuple10[V,V,V,V,V,V,V,V,V,V]) = 10; } implicit def tuple11[V] : LiteralRow[Tuple11[V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple11[V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple11[V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); } def length(tup : Tuple11[V,V,V,V,V,V,V,V,V,V,V]) = 11; } implicit def tuple12[V] : LiteralRow[Tuple12[V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple12[V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple12[V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); } def length(tup : Tuple12[V,V,V,V,V,V,V,V,V,V,V,V]) = 12; } implicit def tuple13[V] : LiteralRow[Tuple13[V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple13[V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple13[V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); } def length(tup : Tuple13[V,V,V,V,V,V,V,V,V,V,V,V,V]) = 13; } implicit def tuple14[V] : LiteralRow[Tuple14[V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple14[V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple14[V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); } def length(tup : Tuple14[V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 14; } implicit def tuple15[V] : LiteralRow[Tuple15[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple15[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple15[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); fn(14, tup._15); } def length(tup : Tuple15[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 15; } implicit def tuple16[V] : LiteralRow[Tuple16[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple16[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple16[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); fn(14, tup._15); fn(15, tup._16); } def length(tup : Tuple16[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 16; } implicit def tuple17[V] : LiteralRow[Tuple17[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple17[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple17[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); fn(14, tup._15); fn(15, tup._16); fn(16, tup._17); } def length(tup : Tuple17[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 17; } implicit def tuple18[V] : LiteralRow[Tuple18[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple18[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple18[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); fn(14, tup._15); fn(15, tup._16); fn(16, tup._17); fn(17, tup._18); } def length(tup : Tuple18[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 18; } implicit def tuple19[V] : LiteralRow[Tuple19[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple19[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple19[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); fn(14, tup._15); fn(15, tup._16); fn(16, tup._17); fn(17, tup._18); fn(18, tup._19); } def length(tup : Tuple19[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 19; } implicit def tuple20[V] : LiteralRow[Tuple20[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple20[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple20[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); fn(14, tup._15); fn(15, tup._16); fn(16, tup._17); fn(17, tup._18); fn(18, tup._19); fn(19, tup._20); } def length(tup : Tuple20[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 20; } implicit def tuple21[V] : LiteralRow[Tuple21[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple21[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple21[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); fn(14, tup._15); fn(15, tup._16); fn(16, tup._17); fn(17, tup._18); fn(18, tup._19); fn(19, tup._20); fn(20, tup._21); } def length(tup : Tuple21[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 21; } implicit def tuple22[V] : LiteralRow[Tuple22[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] = new LiteralRow[Tuple22[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V],V] { def foreach[X](tup : Tuple22[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V], fn : ((Int,V) => X)) = { fn(0, tup._1); fn(1, tup._2); fn(2, tup._3); fn(3, tup._4); fn(4, tup._5); fn(5, tup._6); fn(6, tup._7); fn(7, tup._8); fn(8, tup._9); fn(9, tup._10); fn(10, tup._11); fn(11, tup._12); fn(12, tup._13); fn(13, tup._14); fn(14, tup._15); fn(15, tup._16); fn(16, tup._17); fn(17, tup._18); fn(18, tup._19); fn(19, tup._20); fn(20, tup._21); fn(21, tup._22); } def length(tup : Tuple22[V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V]) = 22; } } ================================================ FILE: src/main/scala/scalala/tensor/Matrix.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.{DomainException,IndexDomain,TableDomain} import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; import dense.DenseMatrix; /** * Implementation trait for a matrix. * * @author dramage */ trait MatrixLike[@specialized(Int,Long,Float,Double) V, +This<:Matrix[V]] extends Tensor2Like[Int,Int,V,IndexDomain,IndexDomain,TableDomain,TableDomain,This] { self => /** Number of rows in this table. */ def numRows : Int; /** Number of columsn in this table. */ def numCols : Int; override def size = numRows * numCols; override def domain = TableDomain(numRows, numCols); override def checkKey(row : Int, col : Int) { if (row < 0 || row >= numRows || col < 0 || col >= numCols) throw new DomainException("Index "+(row,col)+" out of range. Size is "+numRows+"x"+numCols); } override def foreachKey[U](fn : ((Int,Int))=>U) = for (i <- 0 until numRows; j <- 0 until numCols) fn((i,j)); /** Returns true if this matrix has the same number of rows as columns. */ def isSquare : Boolean = numRows == numCols; /** Returns true if this matrix is symmetric. */ def isSymmetric : Boolean = { if (!isSquare) return false; var i = 0; while (i < numRows) { var j = i + 1; while (j < numCols) { if (this(i,j) != this(j,i)) { return false; } j += 1; } i += 1; } return true; } /** Returns the sum of the diagonal elements of this matrix. */ def trace(implicit add : BinaryOp[V,V,OpAdd,V]) : V = { var rv = this(0,0); var i = 1; var n = math.min(numRows, numCols); while (i < n) { rv = add(rv, this(i,i)); i += 1; } rv; } /** Returns a copy of this matrix as a DenseMatrix. */ def toDense : DenseMatrix[V] = { val rv = DenseMatrix.zeros(numRows, numCols); rv := repr; rv; } def toString(maxLines : Int = ScalalaConsole.terminalHeight - 3, maxWidth : Int = ScalalaConsole.terminalWidth, mkValueString : V=>String = buildMkValueString) : String = { val showRows = if (numRows > maxLines) maxLines - 1 else numRows; def colWidth(col : Int) = (0 until showRows).map(row => mkValueString(this(row,col)).length+2).max; val colWidths = new scala.collection.mutable.ArrayBuffer[Int]; var col = 0; while (col < numCols && colWidths.sum < maxWidth) { colWidths += colWidth(col); col += 1; } // make space for "... (K total)" if (colWidths.size < numCols) { while (colWidths.sum + numCols.toString.length + 12 >= maxWidth) { if (colWidths.isEmpty) { return "%d x %d matrix".format(numRows, numCols); } colWidths.remove(colWidths.length - 1); } } val newline = System.getProperty("line.separator"); var rv = new scala.StringBuilder; for (row <- 0 until showRows; col <- 0 until colWidths.length) { val cell = mkValueString(this(row,col)); rv.append(cell); rv.append(" " * (colWidths(col) - cell.length)); if (col == colWidths.length - 1) { if (col < numCols - 1) { rv.append("..."); if (row == 0) { rv.append(" ("); rv.append(numCols); rv.append(" total)"); } } if (row + 1 < showRows) { rv.append(newline); } } } if (numRows > showRows) { rv.append(newline); rv.append("... ("); rv.append(numRows); rv.append(" total)"); } rv.toString; } override def toString : String = toString(maxLines = ScalalaConsole.terminalHeight - 3, maxWidth = ScalalaConsole.terminalWidth, mkValueString = buildMkValueString); override protected def canEqual(other : Any) : Boolean = other match { case that : Matrix[_] => true; case _ => false; } override def t : Matrix[V] = new MatrixTranspose.Impl[V,Matrix[V]](repr); // // row and column accessors // // def rows[TT:>This,That](implicit CanSliceRow[TT,K1,That]) : Tensor2RowsMonadic[K2,V,This,That] = // new Tensor2RowsMonadic[K2,V,This,That] { override def repr = self.repr; } // // def cols[TT:>This,That](implicit CanSliceCol[TT,K2,That]) : Tensor2ColsMonadic[K1,V,This,That] = // new Tensor2ColsMonadic[K1,V,This,That] { override def repr = self.repr; } } trait Matrix[@specialized(Int,Long,Float,Double) V] extends Tensor2[Int,Int,V] with MatrixLike[V,Matrix[V]]; object Matrix { implicit def canSliceRow[V:Scalar] : CanSliceRow[Matrix[V],Int,VectorRow[V]] = new CanSliceRow[Matrix[V],Int,VectorRow[V]] { override def apply(from : Matrix[V], row : Int) = new RowSliceImpl[V,Matrix[V]](from,row); } implicit def canSliceCol[V:Scalar] : CanSliceCol[Matrix[V],Int,VectorCol[V]] = new CanSliceCol[Matrix[V],Int,VectorCol[V]] { override def apply(from : Matrix[V], col : Int) = new ColSliceImpl[V,Matrix[V]](from, col); } implicit def canSliceMatrix[V:Scalar] : CanSliceMatrix[Matrix[V],Int,Int,Matrix[V]] = new CanSliceMatrix[Matrix[V],Int,Int,Matrix[V]] { override def apply(from : Matrix[V], keys1 : Seq[Int], keys2 : Seq[Int]) = new MatrixSliceImpl[V,Matrix[V]](from, keys1, keys2); } trait RowSliceLike[V,+Coll<:Matrix[V],+This<:RowSlice[V,Coll]] extends VectorSliceLike[(Int,Int),TableDomain,V,Coll,This] with VectorRowLike[V,This] { def row : Int; override val domain = underlying.domain._2; override def length = underlying.numCols; override def lookup(key : Int) = (row,key); } trait RowSlice[V,+Coll<:Matrix[V]] extends VectorSlice[(Int,Int),V,Coll] with VectorRow[V] with RowSliceLike[V,Coll,RowSlice[V,Coll]]; class RowSliceImpl[V,+Coll<:Matrix[V]] (override val underlying : Coll, override val row : Int) (implicit override val scalar : Scalar[V]) extends RowSlice[V,Coll]; trait ColSliceLike[V,+Coll<:Matrix[V],+This<:ColSlice[V,Coll]] extends VectorSliceLike[(Int,Int),TableDomain,V,Coll,This] with VectorColLike[V,This] { def col : Int; override def domain = underlying.domain._1; override def length = underlying.numRows; override def lookup(key : Int) = (key,col); } trait ColSlice[V,+Coll<:Matrix[V]] extends VectorSlice[(Int,Int),V,Coll] with VectorCol[V] with ColSliceLike[V,Coll,ColSlice[V,Coll]]; class ColSliceImpl[V,+Coll<:Matrix[V]] (override val underlying : Coll, override val col : Int) (implicit override val scalar : Scalar[V]) extends ColSlice[V,Coll]; trait MatrixSliceLike[@specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Matrix[V], +This<:MatrixSlice[V,Coll]] extends TensorSliceLike[(Int,Int),TableDomain,(Int,Int),TableDomain,V,Coll,This] with MatrixLike[V,This] { def lookup1(i : Int) : Int; def lookup2(j : Int) : Int; /* final */ override def lookup(tup : (Int,Int)) = (lookup1(tup._1), lookup2(tup._2)); override def apply(i : Int, j : Int) : V = underlying.apply(lookup1(i), lookup2(j)); } trait MatrixSlice[@specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Matrix[V]] extends TensorSlice[(Int,Int),(Int,Int),V,Coll] with Matrix[V] with MatrixSliceLike[V,Coll,MatrixSlice[V,Coll]]; class MatrixSliceImpl[V, +Coll<:Matrix[V]] (override val underlying : Coll, val keys1 : Seq[Int], val keys2 : Seq[Int]) (implicit override val scalar : Scalar[V]) extends MatrixSlice[V, Coll] { override def numRows = keys1.size; override def numCols = keys2.size; override def lookup1(i : Int) = keys1(i); override def lookup2(j : Int) = keys2(j); override val domain = TableDomain(keys1.length, keys2.length); } implicit def canMulMatrixByMatrix[ @specialized(Int,Double) V1, A, ARow, ADomainRow, InnerDomain, ADomain, @specialized(Int,Double) V2, B, BCol, BDomainCol, BDomain, @specialized(Int,Double) RV, RDomain, That] (implicit viewA : A=>Matrix[V1], sliceA : CanSliceRow[A,Int,ARow], viewB : B=>Matrix[V2], sliceB : CanSliceCol[B,Int,BCol], mul : BinaryOp[ARow,BCol,OpMulRowVectorBy,RV], bf : CanBuildTensorFrom[A,TableDomain,(Int,Int),RV,That], scalar : Scalar[RV]) : BinaryOp[A, B, OpMulMatrixBy, That] = new BinaryOp[A, B, OpMulMatrixBy, That] { override def opType = OpMulMatrixBy; override def apply(a : A, b : B) = { val domain = new TableDomain(a.numRows,b.numCols) val builder = bf(a, domain); for (i <- a.domain._1; j <- b.domain._2) { builder(i->j) = mul(sliceA(a,i), sliceB(b,j)); } builder.result; } } // implicit def canAppendMatrixColumns[V] // : CanAppendColumns[Bound[V],Matrix[V],Matrix[V]] // = new CanAppendColumns[Bound[V],Matrix[V],Matrix[V]] { // override def apply(a : Bound[V], b : Matrix[V]) = { // require(a.numRows == b.numRows, "Arguments must have same number of rows"); // implicit val sv = a.scalar; // val builder = a.newBuilder[(Int,Int),V](TableDomain(a.numRows, a.numCols+b.numCols)); // a.foreachNonZero((i,j,v) => builder((i,j)) = v); // b.foreachNonZero((i,j,v) => builder((i,j+a.numCols)) = v); // builder.result.asInstanceOf[Matrix[V]]; // } // } // // implicit def canAppendVectorColumn[V] // : CanAppendColumns[Bound[V],VectorCol[V],Matrix[V]] // = new CanAppendColumns[Bound[V],VectorCol[V],Matrix[V]] { // override def apply(a : Bound[V], b : VectorCol[V]) = { // require(a.numRows == b.size, "Arguments must have same number of rows"); // implicit val sv = a.scalar; // val builder = a.newBuilder[(Int,Int),V](TableDomain(a.numRows, a.numCols+1)); // a.foreachNonZero((i,j,v) => builder((i,j)) = v); // b.foreachNonZero((i,v) => builder((i,a.numCols)) = v); // builder.result.asInstanceOf[Matrix[V]]; // } // } } ================================================ FILE: src/main/scala/scalala/tensor/MatrixSingularException.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; /** * Thrown when trying to sovle using a singular matrix. * * @author dramage */ class MatrixSingularException(msg : String) extends RuntimeException(msg) { def this() = this(null); } ================================================ FILE: src/main/scala/scalala/tensor/MatrixTranspose.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.{IndexDomain,TableDomain}; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * A Transpose of any Matrix type is a Matrix. * * @author dramage */ trait MatrixTransposeLike [@specialized(Int,Long,Float,Double) V, +Coll <: Matrix[V], +This <: MatrixTranspose[V,Coll]] extends Tensor2TransposeLike[Int,Int,V,IndexDomain,IndexDomain,TableDomain,TableDomain,Coll,This] with MatrixLike[V,This] { override def domain = underlying.domain.transpose.asInstanceOf[TableDomain]; override def numRows = underlying.numCols; override def numCols = underlying.numRows; override def t : Coll = underlying; } /** * A Transpose of any Matrix type is a Matrix. * * @author dramage */ trait MatrixTranspose[@specialized(Int,Long,Float,Double) B, +Coll <: Matrix[B]] extends Tensor2Transpose[Int,Int,B,Coll] with Matrix[B] with MatrixTransposeLike[B, Coll, MatrixTranspose[B, Coll]]; object MatrixTranspose { class Impl[B, +Coll <: Matrix[B]] (override val underlying : Coll) (implicit override val scalar : Scalar[B]) extends MatrixTranspose[B,Coll]; } ================================================ FILE: src/main/scala/scalala/tensor/SelectAll.scala ================================================ package scalala.tensor /** * For selecting all elements from a matrix row or column. * See :: literal. * * @author dramage */ sealed trait SelectAll; /** * For selecting all elements from a matrix row or column. * * @author dramage */ object :: extends SelectAll; ================================================ FILE: src/main/scala/scalala/tensor/Tensor.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain._; import generic._; import scalala.operators._; import scalala.scalar.{Scalar,ScalarDecimal}; import scalala.generic.collection._; import scalala.generic.math.{CanMean,CanVariance,CanSqrt}; /** * A Tensor is a map from keys K (with a domain) to numeric scalar values V. * More specific operations are available on tensors indexed by a single key * (Tensor1, Vector) or pair of keys (Tensor2, Matrix). * * Note that this trait does not support for comprehensions, although its * two sub-traits: TensorSeqLike and TensorMapLike do. The difference is * the way in which the collection is viewed. TensorSeqLike views the * collection as one containing values. TensorMapLike views the collection * as one containing key value pairs. * * @author dramage */ trait TensorLike [@specialized(Int, Long) K, @specialized(Int, Long, Float, Double, Boolean) V, +D<:IterableDomain[K], +This<:Tensor[K,V]] extends DomainFunction[K, V, D] with operators.NumericOps[This] with HasValuesMonadic[This,V] { self => type Domain = D; protected type Self = This; /** Returns a pointer to this cast as an instance of This. */ def repr : This = this.asInstanceOf[This]; /** Provides information about the underlying scalar value type V. */ implicit val scalar : Scalar[V]; /** * Returns a builder for constructing new instances like this one, * on the given domain. */ def newBuilder[NK,NV](domain : IterableDomain[NK])(implicit scalar : Scalar[NV]) : TensorBuilder[NK,NV,Tensor[NK,NV]] = domain match { case that : IndexDomain => mutable.Vector[NV](that)(scalar).asBuilder; case that : Domain1[_] => mutable.Tensor1[NK,NV](that.asInstanceOf[Domain1[NK]])(scalar).asBuilder; case that : TableDomain => mutable.Matrix[NV](that)(scalar).asBuilder; case that : Domain2[_,_] => mutable.Tensor2[Any,Any,NV](that.asInstanceOf[Domain2[Any,Any]])(scalar).asBuilder.asInstanceOf[TensorBuilder[NK,NV,Tensor[NK,NV]]]; // TODO: add this in when we have a mutable.TensorN // case that : ProductNDomain[_] => // mutable.TensorN(that)(implicitly[Scalar[NV]]).asBuilder; case _ => mutable.Tensor[NK,NV](domain).asBuilder; } // // Collection contents // /** The size of this collection. */ def size : Int; /** An upper bound on the number of non zero values in this collection. */ def nonzeroSize = size; /** * Returns the pairs of (K,V) that make up this tensor for use in * for comprehensions. The returned object can be viewed as a * Map[K,V]. */ def pairs : TensorPairsMonadic[K,V,This] = new TensorPairsMonadic[K,V,This] { override def repr = self.repr; } /** * Returns the keys that make up this tensor for use in * for comprehensions. The returned object can be viewed as an * Iterable[K]. */ def keys : TensorKeysMonadic[K,V,This] = new TensorKeysMonadic[K,V,This] { override def repr = self.repr; } /** * Returns the values that make up this tensor for use in * for comprehensions. The returned object can be viewed as an * Iterable[V]. */ def values : TensorValuesMonadic[K,V,This] = new TensorValuesMonadic[K,V,This] { override def repr = self.repr; } /** * Returns a monadic nonzero elements of this tensor. Then call one of * .pairs .keys or .values for use in for comprehensions. */ def nonzero : TensorNonZeroMonadic[K,V,This] = new TensorNonZeroMonadic[K,V,This] { override def repr = self.repr; } /** * Applies the given function to each key and its corresponding value. */ def foreachPair[U](fn: (K,V) => U) : Unit = foreachKey[U](k => fn(k,apply(k))); /** * Applies the given function to each key and its corresponding value * if the value is non-zero (and possibly also some that are zeros). * * @return true if all elements in the tensor were visited. */ def foreachNonZeroPair[U](fn : ((K,V)=>U)) : Boolean = { this.foreachPair[U](fn); true; } /** Applies the given function to each key in the tensor. */ def foreachKey[U](fn: K => U) : Unit = domain.foreach[U](fn); /** * Applies the given function to each key if its corresponding value * is non-zero (and possibly some zero-valued keys as well). * * @return true if all keys in the tensor were visisted. */ def foreachNonZeroKey[U](fn : K => U) : Boolean = { this.foreachKey[U](fn); true; } /** * Applies the given function to each value in the map (one for * each element of the domain, including zeros). */ def foreachValue[U](fn : (V=>U)) = foreachKey[U](k => fn(apply(k))); /** * Applies the given function to every non-zero value in the map * (and possibly some zeros, too). * * @return true if all elements in the map were visited. */ def foreachNonZeroValue[U](fn : (V=>U)) = { this.foreachValue[U](fn); true; } /** Returns true if and only if the given predicate is true for all elements. */ def forallPairs(fn : (K,V) => Boolean) : Boolean = { foreachPair((k,v) => if (!fn(k,v)) return false); return true; } /** Returns true if and only if the given predicate is true for all elements. */ def forallValues(fn : V => Boolean) : Boolean = { foreachValue(v => if (!fn(v)) return false); return true; } /** Returns true if and only if the given predicate is true for all non-zero elements. */ def forallNonZeroPairs(fn : (K,V) => Boolean) : Boolean = { foreachNonZeroPair((k,v) => if (!fn(k,v)) return false); return true; } /** Returns true if and only if the given predicate is true for all non-zero elements. */ def forallNonZeroValues(fn : V => Boolean) : Boolean = { foreachNonZeroValue(v => if (!fn(v)) return false); return true; } /** Creates a new map containing a transformed copy of this map. */ def mapPairs[TT>:This,O,That](f : (K,V) => O) (implicit bf : CanMapKeyValuePairs[TT, K, V, O, That]) : That = bf.map(repr, f); /** Maps all non-zero key-value pairs values. */ def mapNonZeroPairs[TT>:This,O,That](f : (K,V) => O) (implicit bf : CanMapKeyValuePairs[TT, K, V, O, That]) : That = bf.mapNonZero(repr.asInstanceOf[TT], f); /** Creates a new map containing a transformed copy of this map. */ def mapValues[TT>:This,O,That](f : V => O) (implicit bf : CanMapValues[TT, V, O, That]) : That = bf.map(repr.asInstanceOf[TT], f); /** Maps all non-zero values. */ def mapNonZeroValues[TT>:This,O,That](f : V => O) (implicit bf : CanMapValues[TT, V, O, That]) : That = bf.mapNonZero(repr.asInstanceOf[TT], f); /** Iterates over the keys in the tensor. */ def keysIterator : Iterator[K] = domain.iterator; /** Iterates over the (possibly) non-zero keys in the tensor. */ def keysIteratorNonZero : Iterator[K] = keysIterator; /** Iterates over the values in the tensor. */ def valuesIterator : Iterator[V] = keysIterator.map(apply); /** Iterates over the (possibly) non-zero values in the tensor. */ def valuesIteratorNonZero : Iterator[V] = valuesIterator; /** Iterates over all elements in the domain and the corresponding value. */ def pairsIterator : Iterator[(K,V)] = keysIterator.map(k => (k,this(k))); /** Iterates over the (possibly) non-zero pairs in the tensor. */ def pairsIteratorNonZero : Iterator[(K,V)] = pairsIterator; /** Returns some key for which the given predicate is true. */ def find(p : V => Boolean) : Option[K] = { foreachKey(k => if (p(apply(k))) return Some(k)); return None; } /** Returns the keys for which the given predicate is true. */ def findAll(p : V => Boolean) : Iterator[K] = keysIterator.filter(this andThen p); /** * Constructs a view of this map on which calls to mapValues are * chained together and lazily evaluated. */ def view[That](implicit bf : CanView[This,That]) : That = bf.apply(repr); /** * Creates a new Tensor over the same domain using the given value * function to create each return value in the map. */ def joinAll[TT>:This,V2,RV,That](tensor : Tensor[K,V2])(fn : (K,V,V2) => RV) (implicit jj : CanJoin[TT, Tensor[K,V2], K, V, V2]) : Unit = jj.joinAll[RV](repr.asInstanceOf[TT], tensor, (k,v1,v2) => fn(k,v1,v2)); /** * Creates a new Tensor over the same domain using the given value * function to create each return value in the map where keys in * both this and m are non-zero. */ def joinBothNonZero[TT>:This,V2,RV,That](tensor : Tensor[K,V2])(fn : (K,V,V2) => RV) (implicit jj : CanJoin[TT, Tensor[K,V2], K, V, V2]) : Unit = jj.joinBothNonZero[RV](repr.asInstanceOf[TT], tensor, (k,v1,v2) => fn(k,v1,v2)); /** * Creates a new Tensor over the same domain using the given value * function to create each return value in the map where keys in * either this or m are non-zero. */ def joinEitherNonZero[TT>:This,V2,RV,That](tensor : Tensor[K,V2])(fn : (K,V,V2) => RV) (implicit jj : CanJoin[TT, Tensor[K,V2], K, V, V2]) : Unit = jj.joinEitherNonZero[RV](repr.asInstanceOf[TT], tensor, (k,v1,v2) => fn(k,v1,v2)); // // Slice construction // /** The value at the given key. Takes precedence over apply(keys : K*). */ def apply(key : K) : V; /** Creates a view backed by the given keys, returning them as a sequence. */ def apply[That](keys : K*) (implicit bf : CanSliceVector[This, K, That]) : That = bf(repr, keys); /** Creates a view backed by the "true" elements in selected. */ def apply[That](selected : Tensor[K,Boolean]) (implicit bf : CanSliceVector[This, K, That]) : That = bf(repr, domain.filter(selected).toIndexedSeq); /** Creates a view backed by the given keys, returning them as a sequence. */ def apply[That](keys : TraversableOnce[K]) (implicit bf : CanSliceVector[This, K, That]) : That = bf(repr, keys.toIndexedSeq); /** Creates a view for the given elements with new indexes I, backed by this map. */ def apply[I,That](keys : (I,K)*) (implicit bf : CanSliceTensor[This, K, I, That]) : That = apply[I,That](keys.toMap[I,K](Predef.conforms[(I, K)])); /** Creates a view for the given elements with new indexes I, backed by this map. */ def apply[I,That](keys : TraversableOnce[(I,K)]) (implicit bf : CanSliceTensor[This, K, I, That]) : That = apply[I,That](keys.toMap[I,K](Predef.conforms[(I, K)])); /** Creates a view for the given elements with new indexes I, backed by this map. */ def apply[I,That](keys : scala.collection.Map[I,K]) (implicit bf : CanSliceTensor[This, K, I, That]) : That = bf(repr, keys); // // Sorting // /** * Returns the elements of this.domain ordered by their values in this map. * Currently this method is not particularly efficient, as it creates several * in-memory arrays the size of the domain. */ def argsort(implicit ord : Ordering[V]) : List[K] = keys.toList.sortWith((i:K, j:K) => ord.lt(this(i), this(j))); /** * Returns a sorted view of the current map. Equivalent to calling * x(x.argsort). Changes to the sorted view are * written-through to the underlying map. */ def sorted[That](implicit bf : CanSliceVector[This, K, That], ord : Ordering[V]) : That = this.apply[That](this.argsort); // // Collection level queries // /** Returns a key associated with the largest value in the tensor. */ def argmax : K = { if (!pairsIterator.hasNext) { throw new UnsupportedOperationException("Empty .max"); } var (arg,max) = pairsIterator.next; foreachPair((k,v) => if (scalar.>(v, max)) { max = v; arg = k; }); arg; } /** Returns a key associated with the smallest value in the tensor. */ def argmin : K = { if (!pairsIterator.hasNext) { throw new UnsupportedOperationException("Empty .min"); } var (arg,min) = pairsIterator.next; foreachPair((k,v) => if (scalar.<(v,min)) { min = v; arg = k; }); arg; } /** Returns the max of the values in this tensor. */ def max : V = { if (!valuesIterator.hasNext) { throw new UnsupportedOperationException("Empty .max"); } var max = valuesIterator.next; if (foreachNonZeroValue(v => { max = scalar.max(max,v) })) { return max; } else { return scalar.max(max, scalar.zero); } } /** Returns the min of the values in this tensor. */ def min : V = { if (!valuesIterator.hasNext) { throw new UnsupportedOperationException("Empty .min"); } var min = valuesIterator.next; if (foreachNonZeroValue(v => { min = scalar.min(min,v); })) { return min; } else { return scalar.min(min, scalar.zero) } } /** Returns the sum of the values in this tensor. */ def sum : V = { var sum = scalar.zero; foreachNonZeroValue(v => sum = scalar.+(sum,v)); return sum; } /** * Returns the mean of the values in this tensor. * The returned type is a decimal version of the scalar type of this tensor. */ def mean[D](implicit calc : CanMean[This,D]) : D = calc(repr); /** * Returns the variance of the values in this tensor. * The returned type is a decimal version of the scalar type of this tensor. */ def variance[D](implicit calc : CanVariance[This,D]) : D = calc(repr); /** * Returns the standard deviation of the values in this tensor. * The returned type is a decimal version of the scalar type of this tensor. */ def stddev[D](implicit calc : CanVariance[This,D], sqrt : CanSqrt[D,D]) : D = sqrt(calc(repr)); // // Conversions // /** Returns an ordering over the domain based on the values in this map. */ def asOrdering(implicit ord : Ordering[V]) : Ordering[K] = new Ordering[K] { override def compare(a : K, b : K) = ord.compare(self(a), self(b)); } /** Returns an unmodifiable Map-like view of this Tensor. */ def asMap : scala.collection.Map[K,V] = pairs; /** Creates a new copy of this Tensor as a scala map. */ def toMap : Map[K,V] = asMap.toMap; protected[this] def buildMkValueString : V=>String = { if (scalar == implicitly[Scalar[Double]]) (v : V) => String.format("% g".format(v.asInstanceOf[Double])); else if (scalar == implicitly[Scalar[Float]]) (v : V) => String.format("% g".format(v.asInstanceOf[Float])); else (v : V) => v.toString; } protected[this] def buildMkKeyString : K=>String = { (k : K) => k.toString; } /** * Creates a string for the first n non-zero items using the given key string * and value string builder. */ def toString(n : Int, mkKeyString : K=>String, mkValueString : V=>String) : String = { val iter = keysIterator; val keys = iter.take(n).toList; if (keys.isEmpty) return ""; val newline = System.getProperty("line.separator"); val keyWidth = keys.iterator.map(mkKeyString).map(_.length).max+1; val rv = (for (key <- nonzero.keys.iterator) yield { val ks = mkKeyString(key); ks + (" " * (keyWidth-ks.length)) + mkValueString(apply(key)); }).mkString(newline); if (iter.hasNext) { rv + newline + "... ("+(domain.size) +" total)"; } else { rv; } } /** * Creates a string representation of the first 10 (potentially) non-zero * items in the tensor. */ override def toString : String = { toString(10, buildMkKeyString, buildMkValueString); } // // Equality // /** * Default implementation iterates the full domain in order, checking * that each function returns the same value. */ override def equals(other : Any) : Boolean = other match { case that: Tensor[_,_] => (this eq that) || (that canEqual this) && (this.domain == that.domain) && ({ val casted = that.asInstanceOf[Tensor[K,V]]; this.joinEitherNonZero(casted) { (k,v1,v2) => if (v1 != v2) return false; } true; }); case _ => false; } /** From recipe in "Programming in Scala" section 28.4. */ protected def canEqual(other : Any) : Boolean = other match { case that : Tensor[_,_] => true; case _ => false; } override def hashCode() = domain.hashCode + pairsIterator.foldLeft(1)((hash,v) => 41 * hash + v.hashCode); } /** * K Tensor is a map from keys K (with a domain) to numeric scalar values V. * More specific operations are available on tensors indexed by a single key * (Tensor1, Vector) or pair of keys (Tensor2, Matrix). * * @author dramage */ trait Tensor [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V] extends TensorLike[K, V, IterableDomain[K], Tensor[K, V]]; object Tensor { /** Constructs a tensor for the given domain. */ def apply[K,V:Scalar](domain : IterableDomain[K]) = mutable.Tensor.apply(domain); implicit def canView[K, V:Scalar] = new CanView[Tensor[K,V],TensorView.IdentityView[K,V,Tensor[K,V]]] { override def apply(from : Tensor[K,V]) = new TensorView.IdentityViewImpl[K,V,Tensor[K,V]](from); } implicit def canSliceTensor[K1, K2, V:Scalar] = new CanSliceTensor[Tensor[K1,V], K1, K2, Tensor[K2,V]] { override def apply(from : Tensor[K1,V], keymap : scala.collection.Map[K2,K1]) = new TensorSlice.FromKeyMap[K1, K2, V, Tensor[K1,V]](from, keymap); } implicit def canSliceVectorCol[K, V:Scalar] = new CanSliceVector[Tensor[K,V], K, VectorCol[V]] { override def apply(from : Tensor[K,V], keys : Seq[K]) = new VectorColSlice.FromKeySeq[K,V,Tensor[K,V]](from, keys); } implicit def canMapValues[K, V, RV, This, D, That] (implicit view : This=>Tensor[K,V], d : CanGetDomain[This,D], bf : CanBuildTensorFrom[This, D, K, RV, That], s : Scalar[RV]) : CanMapValues[This,V,RV,That] = new CanMapValues[This,V,RV,That] { override def map(from : This, fn : (V=>RV)) = { val builder = bf(from, from.domain.asInstanceOf[D]); from.foreachPair((k,v) => builder(k) = fn(v)); builder.result; } override def mapNonZero(from : This, fn : (V=>RV)) = { val builder = bf(from, from.domain.asInstanceOf[D]); from.foreachNonZeroPair((k,v) => builder(k) = fn(v)); builder.result; } } implicit def canMapKeyValuePairs[K, V, RV, This, D, That] (implicit view : This=>Tensor[K,V], d : CanGetDomain[This,D], bf : CanBuildTensorFrom[This, D, K, RV, That], s : Scalar[RV]) : CanMapKeyValuePairs[This,K,V,RV,That] = new CanMapKeyValuePairs[This,K,V,RV,That] { override def map(from : This, fn : ((K,V)=>RV)) = { val builder = bf(from, from.domain.asInstanceOf[D]); from.foreachPair((k,v) => builder(k) = fn(k,v)); builder.result; } override def mapNonZero(from : This, fn : ((K,V)=>RV)) = { val builder = bf(from, from.domain.asInstanceOf[D]); from.foreachNonZeroPair((k,v) => builder(k) = fn(k,v)); builder.result; } } implicit def canJoin[K, V1, V2, A, B] (implicit viewA : A=>Tensor[K,V1], viewB : B=>Tensor[K,V2]) : CanJoin[A, B, K, V1, V2] = new CanJoin[A, B, K, V1, V2] { override def joinAll[RV](_a : A, _b : B, fn : (K,V1,V2)=>RV) = { val a = viewA(_a); val b = viewB(_b); a.checkDomain(b.domain); val visited = scala.collection.mutable.HashSet[K]() a.foreachPair{(k,aV) => fn(k,aV,b(k)) visited += k }; b.foreachPair{ (k,bV) => if(!visited(k)) { fn(k,a(k),bV) } } } override def joinEitherNonZero[RV](_a : A, _b : B, fn : (K,V1,V2)=>RV) = { val a = viewA(_a); val b = viewB(_b); val aZ = a.scalar.zero; val bZ = b.scalar.zero; a.checkDomain(b.domain); // keys that are visited and are zero (after function application to // catch mutations) var visitedZeros : scala.collection.mutable.HashSet[K] = null; val wholeDomainVisited = a.foreachNonZeroPair((k,aV) => { val bV = b(k); if (aV != aZ || bV != bZ) { fn(k, aV, bV); } // if value in a at k is now zero (possibly after mutation), remember // that we visited it if (a(k) == aZ) { if (visitedZeros == null) { visitedZeros = scala.collection.mutable.HashSet[K](); } visitedZeros += k; } }); if (!wholeDomainVisited || a.domain != b.domain) { b.foreachNonZeroPair((k,bV) => { val aV = a(k); if (aV == aZ && bV != bZ && (visitedZeros == null || !visitedZeros.contains(k))) { fn(k, aV, bV); } }); } } override def joinBothNonZero[RV](_a : A, _b : B, fn : (K,V1,V2)=>RV) = { val a = viewA(_a); val b = viewB(_b); a.checkDomain(b.domain); val aZ = a.scalar.zero; val bZ = b.scalar.zero; if (a.nonzeroSize <= b.nonzeroSize) { a.foreachNonZeroPair((k,aV) => { val bV = b(k); if (aV != aZ && bV != bZ) fn(k, aV, bV); }); } else { b.foreachNonZeroPair((k,bV) => { val aV = a(k); if (aV != aZ && bV != bZ) fn(k, aV, bV); }); } } } implicit def opTensorUnary[K,V,RV,Op<:OpType,This,That] (implicit view : This=>Tensor[K,V], op : UnaryOp[V,Op,RV], bf : CanMapValues[This,V,RV,That]) : UnaryOp[This,Op,That] = new UnaryOp[This,Op,That] { def opType = op.opType; override def apply(from : This) = bf.map(from, op.apply _); } implicit def opTensorTensor[K,D,V1,V2,Op<:OpType,RV,A,B,That] (implicit v1 : A=>Tensor[K,V1], v2 : B=>Tensor[K,V2], df : CanGetDomain[A,D], op : BinaryOp[V1,V2,Op,RV], jj : CanJoin[A,B,K,V1,V2], bf : CanBuildTensorForBinaryOp[A,B,D,K,RV,Op,That]) : BinaryOp[A,B,Op,That] = new BinaryOp[A,B,Op,That] { override def opType = op.opType; override def apply(a : A, b : B) = { val builder = bf(a,b,(a.domain union b.domain).asInstanceOf[D]); if (opType == OpMul) { jj.joinBothNonZero(a,b,(k,v1,v2) => builder(k) = op(v1,v2)); } else if(opType == OpAdd || opType == OpSub) { jj.joinEitherNonZero(a,b,(k,v1,v2) => builder(k) = op(v1,v2)); } else { jj.joinAll(a,b,(k,v1,v2) => builder(k) = op(v1,v2)); } builder.result; } } implicit def opTensorScalar[K,V1,V2,Op<:OpType,RV,This,That] (implicit view : This=>Tensor[K,V1], op : BinaryOp[V1,V2,Op,RV], bf : CanMapValues[This,V1,RV,That], s : Scalar[V2]) : BinaryOp[This,V2,Op,That] = new BinaryOp[This,V2,Op,That] { override def opType = op.opType; override def apply(a : This, b : V2) = { if (opType == OpMul && !s.isNaN(b)) { bf.mapNonZero(a, v => op(v, b)); } else { bf.map(a, v => op(v, b)); } } } implicit def opScalarTensor[K,V1,V2,Op<:OpType,RV,This,That] (implicit view : This=>Tensor[K,V2], op : BinaryOp[V1,V2,Op,RV], bf : CanMapValues[This,V2,RV,That], s : Scalar[V1]) : BinaryOp[V1,This,Op,That] = new BinaryOp[V1,This,Op,That] { override def opType = op.opType; override def apply(a : V1, b : This) = { if (opType == OpMul && !s.isNaN(a)) { bf.mapNonZero(b, v => op(a, v)); } else { bf.map(b, v => op(a, v)); } } } implicit def opTensorInnerProduct[K,V1,V2,A,B,RV] (implicit viewA : A=>Tensor[K,V1], viewB: B=>Tensor[K,V2], mul : BinaryOp[V1,V2,OpMul,RV], add : BinaryOp[RV,RV,OpAdd,RV], compatible : CompatibleShape[A,B], s : Scalar[RV]) : BinaryOp[A,B,OpMulInner,RV] = new BinaryOp[A,B,OpMulInner,RV] { override def opType = OpMulInner; override def apply(a: A, b: B) = { a.checkDomain(b.domain); var sum = s.zero; if (a.nonzeroSize <= b.nonzeroSize) { a.foreachNonZeroPair((k,aV) => sum = add(sum, mul(aV, b(k)))); } else { b.foreachNonZeroPair((k,bV) => sum = add(sum, mul(a(k), bV))); } sum; } } } ================================================ FILE: src/main/scala/scalala/tensor/Tensor1.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain._; import generic.TensorBuilder; import operators.{BinaryOp, OpAdd, OpMul} import scalala.scalar.Scalar; import scalala.generic.collection._; /** * Implementation trait for a one-axis tensor supports methods like norm. * * @author dramage */ trait Tensor1Like [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +D<:Domain1[K], +This<:Tensor1[K,V]] extends TensorLike[K,V,D,This] { self => /** * Constructs a new Tensor1 like this one based on accumulating values * from the given initial start value, like a foldLeft that returns all * intermediate results. */ def accumulate[Z,TT>:This,That](z : Z)(op : (Z,V) => Z) (implicit zs : Scalar[Z], bf : CanBuildTensorFrom[TT,D,K,Z,That]) = { val builder = bf(repr, domain); var acc = z; this.foreachPair((k,v) => { acc = op(acc,v); builder(k) = acc; }); builder.result; } /** * Returns the culumulative sum of this Tensor1. Note that this is only * well defined for domains that have a natural and consistent iteration * order. */ def cumsum[TT>:This,That](implicit bf : CanBuildTensorFrom[TT,D,K,V,That], add : BinaryOp[V,V,OpAdd,V]) : That = accumulate(scalar.zero)(add); /** * Returns the culumulative sum of this Tensor1. Note that this is only * well defined for domains that have a natural and consistent iteration * order. */ def cumprod[TT>:This,That](implicit bf : CanBuildTensorFrom[TT,D,K,V,That], mul : BinaryOp[V,V,OpMul,V]) : That = accumulate(scalar.one)(mul); /** Returns the k-norm of this tensor. */ def norm(n : Double) : Double = { if (n == 1) { var sum = 0.0; foreachNonZeroValue(v => sum += scalar.norm(v)); return sum; } else if (n == 2) { var sum = 0.0; foreachNonZeroValue(v => { val nn = scalar.norm(v); sum += nn * nn }); return math.sqrt(sum); } else if (n == Double.PositiveInfinity) { var max = Double.NegativeInfinity; foreachNonZeroValue(v => { val nn = scalar.norm(v); if (nn > max) max = nn; }); return max; } else { var sum = 0.0; foreachNonZeroValue(v => { val nn = scalar.norm(v); sum += math.pow(nn,n); }); return math.pow(sum, 1.0 / n); } } override protected def canEqual(other : Any) : Boolean = other match { case that : Tensor1[_,_] => true; case _ => false; } } /** * One-axis tensor supports methods like norm * and inner products (dot) with other one-axis tensors. * * @author dramage */ trait Tensor1[@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] extends Tensor[K,V] with Tensor1Like[K,V,Domain1[K],Tensor1[K,V]]; object Tensor1 { /** Constructs a tensor for the given domain. */ def apply[K,V:Scalar](domain : Domain1[K]) : Tensor[K,V] = mutable.Tensor1.apply[K,V](domain); } ================================================ FILE: src/main/scala/scalala/tensor/Tensor1Col.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.{IterableDomain,Domain1,IndexDomain,CanGetDomain,CanBuildDomain2}; import generic.TensorBuilder; import scalala.operators._; import scalala.scalar.Scalar; import scalala.generic.collection.CanBuildTensorFrom; /** * Implementation trait for a one-axis tensor shaped as a column. * * @author dramage */ trait Tensor1ColLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +D<:Domain1[K], +This<:Tensor1Col[K,V]] extends Tensor1Like[K,V,D,This] with operators.ColOps[This] { self => override def newBuilder[K2,V2:Scalar](domain : IterableDomain[K2]) = domain match { case that : IndexDomain => mutable.Vector[V2](that).asBuilder; case that : Domain1[_] => mutable.Tensor1Col[K2,V2](that).asBuilder; case _ => super.newBuilder[K2,V2](domain); } def t : Tensor1Row[K,V] = new Tensor1Row.View[K,V](repr); } /** * One-axis tensor shaped as a column. * * @author dramage */ trait Tensor1Col[@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] extends Tensor1[K,V] with Tensor1ColLike[K,V,Domain1[K],Tensor1Col[K,V]]; object Tensor1Col { class View[K,V](override val inner : Tensor1Row[K,V]) extends Tensor1Proxy[K,V,Tensor1Row[K,V]] with Tensor1Col[K,V] with Tensor1Like[K,V,Domain1[K],View[K,V]] { override def repr : View[K,V] = this; override def t : Tensor1Row[K,V] = inner; } implicit def canMulTensor1ColByRow[K1,K2,V1,V2,RV,A,DA,B,DB,DThat,That] (implicit viewA : A=>Tensor1Col[K1,V1], viewB : B=>Tensor1Row[K2,V2], dA : CanGetDomain[A,DA], dB : CanGetDomain[B,DB], dThat : CanBuildDomain2[DA,DB,DThat], mul : BinaryOp[V1,V2,OpMul,RV], bf : CanBuildTensorFrom[A, DThat, (K1,K2), RV, That]) : BinaryOp[A,B,OpMulColVectorBy,That] = new BinaryOp[A,B,OpMulColVectorBy,That] { override def opType = OpMulColVectorBy; override def apply(a : A, b : B) = { val builder = bf(a, dThat(a.domain.asInstanceOf[DA], b.domain.asInstanceOf[DB])); a.foreachNonZeroPair((i,va) => b.foreachNonZeroPair((j,vb) => builder((i,j)) = mul(va,vb))); builder.result; } } } ================================================ FILE: src/main/scala/scalala/tensor/Tensor1Proxy.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.Domain1; import scalala.scalar.Scalar; import scalala.operators._; /** * Implementation trait for proxies to a Tensor1 instance. * * @author dramage */ trait Tensor1ProxyLike [@specialized(Int,Long)K, @specialized(Int,Long,Float,Double) V, +D<:Domain1[K], Inner<:Tensor1[K,V], +This<:Tensor1[K,V]] extends TensorProxyLike[K,V,D,Inner,This] with Tensor1Like[K,V,D,This] { override def norm(n : Double) = inner.norm(n); } /** * Proxy to a Tensor1 instance. * * @author dramage */ trait Tensor1Proxy [@specialized(Int,Long)K, @specialized(Int,Long,Float,Double) V, Inner<:Tensor1[K,V]] extends TensorProxy[K,V,Inner] with Tensor1[K,V] with Tensor1ProxyLike[K,V,Domain1[K],Inner,Tensor1Proxy[K,V,Inner]]; ================================================ FILE: src/main/scala/scalala/tensor/Tensor1Row.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.{IterableDomain,Domain1,Domain2,IndexDomain}; import generic.{TensorBuilder}; import scalala.generic.collection.{CanSliceCol,CanBuildTensorFrom,CanSliceVector}; import scalala.scalar.Scalar; import scalala.operators._; /** * Implementation trait for a one-axis tensor shaped as a row. * * @author dramage */ trait Tensor1RowLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +D<:Domain1[K], +This<:Tensor1Row[K,V]] extends Tensor1Like[K,V,D,This] with operators.RowOps[This] { self => override def newBuilder[K2,V2:Scalar](domain : IterableDomain[K2]) = domain match { case that : IndexDomain => mutable.VectorRow[V2](that).asBuilder; case that : Domain1[_] => mutable.Tensor1Row[K2,V2](that).asBuilder; case _ => super.newBuilder[K2,V2](domain); } def t : Tensor1Col[K,V] = new Tensor1Col.View[K,V](repr); } /** * One-axis tensor shaped as a row. * * @author dramage */ trait Tensor1Row[@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] extends Tensor1[K,V] with Tensor1RowLike[K,V,Domain1[K],Tensor1Row[K,V]]; object Tensor1Row { class View[K,V](override val inner : Tensor1Col[K,V]) extends Tensor1Proxy[K,V,Tensor1Col[K,V]] with Tensor1Row[K,V] with Tensor1Like[K,V,Domain1[K],View[K,V]] { override def repr : View[K,V] = this; override def t : Tensor1Col[K,V] = inner; } implicit def canMulTensor1RowByCol[K,V1,V2,A,B,RV] (implicit viewA : A=>Tensor1Row[K,V1], viewB : B=>Tensor1Col[K,V2], dot : BinaryOp[A,B,OpMulInner,RV], scalar : Scalar[RV]) : BinaryOp[A,B,OpMulRowVectorBy,RV] = new BinaryOp[A,B,OpMulRowVectorBy,RV] { override def opType = OpMulRowVectorBy; override def apply(a : A, b : B) = dot(a, b); } implicit def canMulTensor1RowByMatrix[K1,K2,V1,V2,Col,RV,ThisA,ThisB,D2<:Domain1[K2],That] (implicit viewA : ThisA => Tensor1Row[K1,V1], viewB : ThisB => Tensor2Like[K1,K2,V2,_,D2,_,_,_], slice : CanSliceCol[ThisB,K2,Col], mul : BinaryOp[ThisA,Col,OpMulRowVectorBy,RV], scalar : Scalar[RV], bf : CanBuildTensorFrom[ThisA,D2,K2,RV,That]) : BinaryOp[ThisA,ThisB,OpMulRowVectorBy,That] = new BinaryOp[ThisA,ThisB,OpMulRowVectorBy,That] { override def opType = OpMulRowVectorBy; override def apply(a : ThisA, b : ThisB) = { val domain = b.domain.asInstanceOf[Domain2[_,_]]._2.asInstanceOf[D2]; val builder : TensorBuilder[K2,RV,That] = bf(a, domain); for (j <- domain.asInstanceOf[Domain1[K2]]) { builder(j) = mul(a, slice(b, j)); } builder.result; } } implicit def canSliceVectorRow[K, V:Scalar] = new CanSliceVector[Tensor[K,V], K, VectorRow[V]] { override def apply(from : Tensor[K,V], keys : Seq[K]) = new VectorRowSlice.FromKeySeq[K,V,Tensor[K,V]](from, keys); } } ================================================ FILE: src/main/scala/scalala/tensor/Tensor1Slice.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.{IterableDomain,Domain1}; /** * Implementation trait for a Tensor1 view of a slice of keys from a Tensor. * * @author dramage */ trait Tensor1SliceLike [@specialized(Int,Long) K1, +D1<:IterableDomain[K1], @specialized(Int,Long) K2, +D2<:Domain1[K2], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K1,V], +This<:Tensor1Slice[K1,K2,V,Coll]] extends TensorSliceLike[K1, D1, K2, D2, V, Coll, This] with Tensor1Like[K2, V, D2, This]; /** * A Tensor1 view of a slice of keys from a Tensor. * * @author dramage */ trait Tensor1Slice [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K1,V]] extends TensorSlice[K1,K2,V,Coll] with Tensor1[K2,V] with Tensor1SliceLike[K1, IterableDomain[K1], K2, Domain1[K2], V, Coll, Tensor1Slice[K1, K2, V, Coll]]; ================================================ FILE: src/main/scala/scalala/tensor/Tensor2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import scalar.Scalar; import domain._; import scalala.generic.collection._; import scalala.operators._; import generic.TensorTriplesMonadic; /** * Implementation trait for tensors indexed by two keys, such as Matrices. * * TODO: Make up mind about whether implementing classes should provide * which one (or both) of the pairs interface and triples interface. * * @author dramage */ trait Tensor2Like [@specialized(Int) K1, @specialized(Int) K2, @specialized(Int,Long,Float,Double,Boolean) V, +D1<:Domain1[K1], +D2<:Domain1[K2], +D<:Domain2[K1,K2], +T<:Domain2[K2,K1], +This<:Tensor2[K1,K2,V]] extends TensorLike[(K1,K2),V,D,This] with operators.MatrixOps[This] { self => def checkKey(k1 : K1, k2 : K2) : Unit = { if (!domain._1.contains(k1) || !domain._2.contains(k2)) { throw new DomainException((k1,k2)+" not in domain"); } } /* final */ override def checkKey(pos : (K1,K2)) : Unit = checkKey(pos._1, pos._2); /** Gets the value indexed by (i,j). */ def apply(i : K1, j : K2) : V; /** Fixed alias for apply(i,j). */ /* final */ override def apply(pos : (K1,K2)) : V = apply(pos._1, pos._2); /** Select all columns within a given row. */ def apply[TT>:This,That](i : K1, j : SelectAll)(implicit bf : CanSliceRow[TT,K1,That]) : That = bf.apply(repr, i); /** Select all rows within a given column. */ def apply[TT>:This,That](i : SelectAll, j : K2)(implicit bf : CanSliceCol[TT,K2,That]) : That = bf.apply(repr, j); /** Select a sub-matrix of the requested rows and columns. */ def apply[TT>:This,That](i : Seq[K1], j : Seq[K2])(implicit bf : CanSliceMatrix[TT,K1,K2,That]) : That = bf.apply(repr, i, j); /** Select all columns for a specified set of rows. */ def apply[TT>:This,That](i : Seq[K1], j : SelectAll)(implicit bf : CanSliceMatrix[TT,K1,K2,That]) : That = bf.apply(repr, i, domain._2.toIndexedSeq); /** Select all rows for a specified set of columns. */ def apply[TT>:This,That](i : SelectAll, j : Seq[K2])(implicit bf : CanSliceMatrix[TT,K1,K2,That]) : That = bf.apply(repr, domain._1.toIndexedSeq, j); /** Select specified columns within a row. */ def apply[TT>:This,That1,That2](i : K1, j : IndexedSeq[K2]) (implicit s1 : CanSliceRow[TT,K1,That1], s2 : CanSliceVector[That1,K2,That2]) : That2 = s2.apply(s1.apply(repr, i), j); /** Select specified rows within a column. */ def apply[TT>:This,That1,That2](i : IndexedSeq[K1], j : K2) (implicit s1 : CanSliceCol[TT,K2,That1], s2 : CanSliceVector[That1,K1,That2]) : That2 = s2.apply(s1.apply(repr, j), i); /** Transpose of the matrix. */ def t : Tensor2[K2,K1,V] = new Tensor2Transpose.Impl[K2,K1,V,This](repr); // // triples accessors // def triples : TensorTriplesMonadic[K1,K2,V,This] = new TensorTriplesMonadic[K1,K2,V,This] { override def repr = self.repr; } def foreachTriple[U](fn : (K1,K2,V)=>U) : Unit = foreachPair((k,v) => fn(k._1, k._2, v)); def foreachNonZeroTriple[U](fn : (K1,K2,V)=>U) : Boolean = foreachNonZeroPair((k,v) => fn(k._1, k._2, v)); def mapTriples[TT>:This,RV,That](fn : (K1,K2,V)=>RV) (implicit bf : CanMapKeyValuePairs[TT, (K1,K2), V, RV, That]) : That = mapPairs[TT,RV,That]((k,v) => fn(k._1,k._2,v))(bf); def mapNonZeroTriples[TT>:This,RV,That](fn : (K1,K2,V)=>RV) (implicit bf : CanMapKeyValuePairs[TT, (K1,K2), V, RV, That]) : That = mapNonZeroPairs[TT,RV,That]((k,v) => fn(k._1,k._2,v))(bf); def triplesIterator : Iterator[(K1,K2,V)] = pairsIterator.map(pair => (pair._1._1,pair._1._2,pair._2)); def triplesIteratorNonZero : Iterator[(K1,K2,V)] = pairsIteratorNonZero.map(pair => (pair._1._1,pair._1._2,pair._2)); // // equality // override protected def canEqual(other : Any) : Boolean = other match { case that : Tensor2[_,_,_] => true; case _ => false; } } /** * Tensors indexed by two keys, such as matrices. * * @author dramage */ trait Tensor2 [@specialized(Int) K1, @specialized(Int) K2, @specialized(Int,Long,Float,Double,Boolean) V] extends Tensor[(K1,K2),V] with Tensor2Like[K1,K2,V,Domain1[K1],Domain1[K2],Domain2[K1,K2],Domain2[K2,K1],Tensor2[K1,K2,V]] object Tensor2 { /** Constructs a tensor for the given domain. */ def apply[K1,K2,V:Scalar](domain : Domain2[K1,K2]) = mutable.Tensor2.apply(domain); implicit def canSliceRow[T2<:Tensor2[K1,K2,V],K1,K2,V:Scalar] : CanSliceRow[Tensor2[K1,K2,V],K1,Tensor1Row[K2,V]] = new CanSliceRow[Tensor2[K1,K2,V],K1,Tensor1Row[K2,V]] { override def apply(from : Tensor2[K1,K2,V], row : K1) = new RowSliceImpl[K1,K2,V,Tensor2[K1,K2,V]](from,row); } implicit def canSliceCol[K1,K2,V:Scalar] : CanSliceCol[Tensor2[K1,K2,V],K2,Tensor1Col[K1,V]] = new CanSliceCol[Tensor2[K1,K2,V],K2,Tensor1Col[K1,V]] { override def apply(from : Tensor2[K1,K2,V], col : K2) = new ColSliceImpl[K1,K2,V,Tensor2[K1,K2,V]](from, col); } implicit def canSliceMatrix[K1,K2,V:Scalar] : CanSliceMatrix[Tensor2[K1,K2,V],K1,K2,Matrix[V]] = new CanSliceMatrix[Tensor2[K1,K2,V],K1,K2,Matrix[V]] { override def apply(from : Tensor2[K1,K2,V], keys1 : Seq[K1], keys2 : Seq[K2]) = new MatrixSliceImpl[K1,K2,V,Tensor2[K1,K2,V]](from, keys1, keys2); } implicit def canMulTensor2ByTensor1Col[ @specialized(Int) K1, @specialized(Int) K2, @specialized(Int,Double) V1, K, AR, ADomainRow, ADomainCol, ADomain, @specialized(Int,Double) V2, V, BD, @specialized(Int,Double) RV, That] (implicit viewA : K=>Tensor2[K1,K2,V1], sliceA : CanSliceRow[K,K1,AR], domainA : CanGetDomain2[K,ADomainRow,ADomainCol,ADomain], viewB : V=>Tensor1Col[K2,V2], mul : BinaryOp[AR,V,OpMulRowVectorBy,RV], bf : CanBuildTensorFrom[V,ADomainRow,K1,RV,That], scalar : Scalar[RV]) : BinaryOp[K, V, OpMulMatrixBy, That] = new BinaryOp[K, V, OpMulMatrixBy, That] { override def opType = OpMulMatrixBy; override def apply(a : K, b : V) = { val builder = bf(b, domainA._1(a)); for (i <- a.domain._1) { builder(i) = mul(sliceA(a,i), b); } builder.result; } } implicit def canMulMatrixByMatrix[ @specialized(Int) K1, @specialized(Int) K2, @specialized(Int) K3, @specialized(Int,Double) V1, A, ARow, ADomainRow, InnerDomain, ADomain, @specialized(Int,Double) V2, B, BCol, BDomainCol, BDomain, @specialized(Int,Double) RV, RDomain, That] (implicit viewA : A=>Tensor2[K1,K2,V1], sliceA : CanSliceRow[A,K1,ARow], domainA : CanGetDomain2[A,ADomainRow,InnerDomain,ADomain], viewB : B=>Tensor2[K2,K3,V2], sliceB : CanSliceCol[B,K3,BCol], domainB : CanGetDomain2[B,InnerDomain,BDomainCol,BDomain], mul : BinaryOp[ARow,BCol,OpMulInner,RV], domainR : CanBuildDomain2[ADomainRow,BDomainCol,RDomain], bf : CanBuildTensorForBinaryOp[A,B,RDomain,(K1,K3),RV,OpMulMatrixBy,That], scalar : Scalar[RV]) : BinaryOp[A, B, OpMulMatrixBy, That] = new BinaryOp[A, B, OpMulMatrixBy, That] { override def opType = OpMulMatrixBy; override def apply(a : A, b : B) = { val domain = domainR(domainA._1(a), domainB._2(b)); val builder = bf(a, b, domain); for (i <- a.domain._1; j <- b.domain._2) { builder((i,j)) = mul(sliceA(a,i), sliceB(b,j)); } builder.result; } } trait RowSliceLike[K1,K2,V,+Coll<:Tensor2[K1,K2,V],+This<:RowSlice[K1,K2,V,Coll]] extends Tensor1SliceLike[(K1,K2),IterableDomain[(K1,K2)],K2,Domain1[K2],V,Coll,This] with Tensor1RowLike[K2,V,Domain1[K2],This] { def row : K1; override def domain = underlying.domain._2; override def size = domain.size; override def lookup(key : K2) = (row,key); } trait RowSlice[K1,K2,V,+Coll<:Tensor2[K1,K2,V]] extends Tensor1Slice[(K1,K2),K2,V,Coll] with Tensor1Row[K2,V] with RowSliceLike[K1,K2,V,Coll,RowSlice[K1,K2,V,Coll]]; class RowSliceImpl[K1,K2,V,+Coll<:Tensor2[K1,K2,V]] (override val underlying : Coll, override val row : K1) (implicit override val scalar : Scalar[V]) extends RowSlice[K1,K2,V,Coll]; trait ColSliceLike[K1,K2,V,+Coll<:Tensor2[K1,K2,V],+This<:ColSlice[K1,K2,V,Coll]] extends Tensor1SliceLike[(K1,K2),IterableDomain[(K1,K2)],K1,Domain1[K1],V,Coll,This] with Tensor1ColLike[K1,V,Domain1[K1],This] { def col : K2; override val domain = underlying.domain._1; override def size = domain.size; override def lookup(key : K1) = (key,col); } trait ColSlice[K1,K2,V,+Coll<:Tensor2[K1,K2,V]] extends Tensor1Slice[(K1,K2),K1,V,Coll] with Tensor1Col[K1,V] with ColSliceLike[K1,K2,V,Coll,ColSlice[K1,K2,V,Coll]]; class ColSliceImpl[K1,K2,V,+Coll<:Tensor2[K1,K2,V]] (override val underlying : Coll, override val col : K2) (implicit override val scalar : Scalar[V]) extends ColSlice[K1,K2,V,Coll]; trait MatrixSliceLike [@specialized(Int) K1, @specialized(Int) K2, @specialized(Int,Long,Float,Double,Boolean) V, +D1<:Domain1[K1], +D2<:Domain1[K2], +D<:Domain2[K1,K2], +T<:Domain2[K2,K1], +Coll<:Tensor2[K1,K2,V], +This<:MatrixSlice[K1,K2,V,Coll]] extends TensorSliceLike[(K1,K2),D,(Int,Int),TableDomain,V,Coll,This] with MatrixLike[V,This] { def lookup1(i : Int) : K1; def lookup2(j : Int) : K2; /* final */ override def lookup(tup : (Int,Int)) = (lookup1(tup._1), lookup2(tup._2)); override def apply(i : Int, j : Int) : V = underlying.apply(lookup1(i), lookup2(j)); } trait MatrixSlice [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor2[K1,K2,V]] extends TensorSlice[(K1,K2),(Int,Int),V,Coll] with Matrix[V] with MatrixSliceLike[K1,K2,V,Domain1[K1],Domain1[K2],Domain2[K1,K2],Domain2[K2,K1],Coll,MatrixSlice[K1,K2,V,Coll]]; class MatrixSliceImpl[K1, K2, V, +Coll<:Tensor2[K1,K2,V]] (override val underlying : Coll, val keys1 : Seq[K1], val keys2 : Seq[K2]) (implicit override val scalar : Scalar[V]) extends MatrixSlice[K1, K2, V, Coll] { override def numRows = keys1.size; override def numCols = keys2.size; override def lookup1(i : Int) = keys1(i); override def lookup2(j : Int) = keys2(j); override val domain = TableDomain(keys1.length, keys2.length); } } ================================================ FILE: src/main/scala/scalala/tensor/Tensor2Transpose.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import scalar.Scalar; import domain.{Domain1,Domain2}; /** * Implementation trait for a transposed view of an underlying Tensor2. * * @author dramage */ trait Tensor2TransposeLike [@specialized(Int) K2, @specialized(Int) K1, @specialized(Int,Long,Float,Double,Boolean) V, +D2<:Domain1[K2], +D1<:Domain1[K1], +T<:Domain2[K2,K1], +D<:Domain2[K1,K2], +Coll<:Tensor2[K1,K2,V], +This<:Tensor2Transpose[K2,K1,V,Coll]] extends TensorSliceLike[(K1,K2),D,(K2,K1),T,V,Coll,This] with Tensor2Like[K2,K1,V,D2,D1,T,D,This] { self => override def domain = underlying.domain.transpose.asInstanceOf[T]; override def size = underlying.size; /* final */ override def lookup(tup : (K2,K1)) = tup.swap; override def apply(i : K2, j : K1) = underlying.apply(j, i); override def t : Coll = underlying; } /** * Transposed view of an underlying Tensor2. * * @author dramage */ trait Tensor2Transpose [@specialized(Int) K2, @specialized(Int) K1, @specialized(Int,Long,Float,Double,Boolean) V, +Coll <: Tensor2[K1,K2,V]] extends TensorSlice[(K1,K2),(K2,K1),V,Coll] with Tensor2[K2,K1,V] with Tensor2TransposeLike[K2,K1,V,Domain1[K2],Domain1[K1],Domain2[K2,K1],Domain2[K1,K2],Coll,Tensor2Transpose[K2,K1,V,Coll]]; object Tensor2Transpose { /** Default implementation. */ class Impl[K2, K1, V, +Coll <: Tensor2[K1,K2,V]] (override val underlying : Coll) (override implicit val scalar : Scalar[V]) extends Tensor2Transpose[K2,K1,V,Coll]; } ================================================ FILE: src/main/scala/scalala/tensor/TensorN.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import scalar.Scalar; import domain.DomainN; /** * Tensors indexed by a sequence of keys. * * @author dramage */ trait TensorNLike[@specialized(Int) K, @specialized(Int,Long,Float,Double,Boolean) V, +This<:TensorN[K,V]] extends TensorLike[Seq[K],V,DomainN[K],This] { /** Gets the value indexed by (i,j). */ /* final */ def apply(k : K*) : V = apply(k : Seq[K]); override protected def canEqual(other : Any) : Boolean = other match { case that : TensorN[_,_] => true; case _ => false; } } trait TensorN[@specialized(Int) K, @specialized(Int,Long,Float,Double,Boolean) V] extends Tensor[Seq[K],V] with TensorNLike[K,V,TensorN[K,V]] object TensorN; ================================================ FILE: src/main/scala/scalala/tensor/TensorProxy.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.IterableDomain; import generic.TensorBuilder; import scalala.scalar.Scalar; import scalala.generic.collection._; /** * Proxy for a Tensor instance. * * @author dramage */ trait TensorProxyLike [@specialized(Int, Long) K, @specialized(Int, Long, Float, Double, Boolean) V, +D<:IterableDomain[K], Inner <: Tensor[K,V], +This<:Tensor[K,V]] extends TensorLike[K,V,D,This] { def inner : Inner; override def repr = inner.asInstanceOf[This]; override def domain = inner.domain.asInstanceOf[D]; override val scalar = inner.scalar; override def size = inner.size; override def nonzeroSize = inner.nonzeroSize; override def newBuilder[NK,NV:Scalar](domain : IterableDomain[NK]) : TensorBuilder[NK,NV,Tensor[NK,NV]] = inner.newBuilder[NK,NV](domain); override def foreachPair[U](fn: (K,V) => U) : Unit = inner.foreachPair(fn); override def foreachKey[U](fn : (K=>U)) = inner.foreachKey(fn); override def foreachValue[U](fn : (V=>U)) = inner.foreachValue(fn); override def foreachNonZeroPair[U](fn : ((K,V)=>U)) : Boolean = inner.foreachNonZeroPair(fn); override def foreachNonZeroValue[U](fn : (V=>U)) = inner.foreachNonZeroValue(fn); override def forallPairs(fn : (K,V) => Boolean) : Boolean = inner.forallPairs(fn); override def forallNonZeroPairs(fn : (K,V) => Boolean) : Boolean = inner.forallNonZeroPairs(fn); override def forallValues(fn : V => Boolean) : Boolean = inner.forallValues(fn); override def forallNonZeroValues(fn : V => Boolean) : Boolean = inner.forallNonZeroValues(fn); override def pairsIterator : Iterator[(K,V)] = inner.pairsIterator; override def keysIterator : Iterator[K] = inner.keysIterator; override def valuesIterator : Iterator[V] = inner.valuesIterator; override def pairsIteratorNonZero : Iterator[(K,V)] = inner.pairsIteratorNonZero; override def keysIteratorNonZero : Iterator[K] = inner.keysIteratorNonZero; override def valuesIteratorNonZero : Iterator[V] = inner.valuesIteratorNonZero; override def find(p : V => Boolean) : Option[K] = inner.find(p); override def findAll(p : V => Boolean) : Iterator[K] = inner.findAll(p); override def apply(key : K) : V = inner(key); override def argsort(implicit ord : Ordering[V]) : List[K] = inner.argsort; override def argmax : K = inner.argmax; override def argmin : K = inner.argmin; override def max : V = inner.max; override def min : V = inner.min; override def sum : V = inner.sum; override def asOrdering(implicit ord : Ordering[V]) = inner.asOrdering; override def asMap = inner.asMap; override def toMap = inner.toMap; override def hashCode() = inner.hashCode; } /** * Proxy for a generic Tensor. * * @author dramage */ trait TensorProxy[@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, Inner <: Tensor[K,V]] extends Tensor[K,V] with TensorProxyLike[K,V,IterableDomain[K],Inner,TensorProxy[K,V,Inner]]; ================================================ FILE: src/main/scala/scalala/tensor/TensorSlice.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import scalar.Scalar; import domain.{IterableDomain,SetDomain}; /** * Implementation trait for slices of an underlying Tensor. A slice * is a pass-through view of a (mapped) subset of the original Tensor's * domain. * * @author dramage */ trait TensorSliceLike [@specialized(Int,Long) K1, +D1<:IterableDomain[K1], @specialized(Int,Long) K2, +D2<:IterableDomain[K2], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K1,V], +This<:TensorSlice[K1,K2,V,Coll]] extends TensorLike[K2,V,D2,This] { self => /** The collection underlying this view. */ protected def underlying: Coll; /** Maps the keys of this domain map to the keys of the underlying maps's. */ def lookup(key : K2) : K1; override def apply(key : K2) = underlying.apply(lookup(key)); override def newBuilder[K2,V2:Scalar](domain : IterableDomain[K2]) = underlying.newBuilder[K2,V2](domain); } /** * Pass-through view of a (key-mapped) subset of an underlying Tensor. * * @author dramage */ trait TensorSlice [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double,Boolean) V, +Coll <: Tensor[K1, V]] extends Tensor[K2,V] with TensorSliceLike[K1, IterableDomain[K1], K2, IterableDomain[K2], V, Coll, TensorSlice[K1, K2, V, Coll]]; object TensorSlice { class FromKeyMap[K1, K2, V, +Coll<:Tensor[K1, V]] (override val underlying : Coll, keymap : scala.collection.Map[K2,K1]) (override implicit val scalar : Scalar[V]) extends TensorSlice[K1, K2, V, Coll] { override def lookup(key : K2) = keymap(key); override def domain = new SetDomain(keymap.keySet); override def size = keymap.size; } } ================================================ FILE: src/main/scala/scalala/tensor/TensorView.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.IterableDomain; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for pass-through views of underlying Tensor. * * @author dramage */ trait TensorViewLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +D<:IterableDomain[K], +Coll <: Tensor[K,_], +This<:TensorView[K,V,Coll]] extends TensorLike[K,V,D,This] { self => /** The collection underlying this view. */ def underlying: Coll; /** Maps to underlying.domain */ override def domain = underlying.domain.asInstanceOf[D]; override def size = underlying.size; /** Views of views should just return this (cast as This) */ def view = repr; } /** * Pass-through view of an underlying Tensor. * * @author dramage */ trait TensorView [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +Coll <: Tensor[K,_]] extends Tensor[K,V] with TensorViewLike[K,V,IterableDomain[K],Coll,TensorView[K,V,Coll]]; object TensorView { trait IdentityViewLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +D<:IterableDomain[K], +Coll <: Tensor[K,V], +This <: IdentityView[K,V,Coll]] extends TensorViewLike[K,V,D,Coll,This] { override def apply(key : K) = underlying.apply(key); } trait IdentityView [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +Coll <: Tensor[K,V]] extends TensorView[K,V,Coll] with IdentityViewLike[K,V,IterableDomain[K],Coll,IdentityView[K,V,Coll]]; /** Returns an unmodified view of the given Tensor. */ class IdentityViewImpl[K, V, +Coll <: Tensor[K,V]] (override val underlying : Coll) (implicit override val scalar : Scalar[V]) extends IdentityView[K,V,Coll]; trait TransformViewLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, @specialized(Int,Long,Float,Double,Boolean) O, +D<:IterableDomain[K], +Coll <: Tensor[K,V], +This <: TransformView[K,V,O,Coll]] extends TensorViewLike[K,O,D,Coll,This] { /** Transform a value in the underlying map to a value in the view. */ def transform(key : K, value : V) : O; override def apply(key : K) = transform(key, underlying.apply(key)); } trait TransformView [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, @specialized(Int,Long,Float,Double,Boolean) O, +Coll <: Tensor[K,V]] extends TensorView[K,O,Coll] with TransformViewLike[K,V,O,IterableDomain[K],Coll,TransformView[K,V,O,Coll]] /** * Returns an unmodified view of the given Tensor with * values transformed by the given function. */ class TransformImpl[K, V, O, +Coll <: Tensor[K,V]] (override val underlying : Coll, fn : ((K,V)=>O)) (implicit override val scalar : Scalar[O]) extends TransformView[K,V,O,Coll] { override def transform(key : K, value : V) = fn(key, value); } implicit def mkTransformCanMapValues[K, V1, V2, V3:Scalar] = new CanMapValues[TransformView[K,V1,V2,Tensor[K,V1]],V2,V3,TransformView[K,V1,V3,Tensor[K,V1]]] { override def map(from : TransformView[K,V1,V2,Tensor[K,V1]], fn : (V2=>V3)) = new TransformImpl[K,V1,V3,Tensor[K,V1]]( from.underlying, ((k:K, v:V1) => fn(from.transform(k,v)))); override def mapNonZero(from : TransformView[K,V1,V2,Tensor[K,V1]], fn : (V2=>V3)) = map(from, fn); } implicit def mkTransformCanMapKeyValuePairs[K, V1, V2, V3:Scalar] = new CanMapKeyValuePairs[TransformView[K,V1,V2,Tensor[K,V1]],K,V2,V3,TransformView[K,V1,V3,Tensor[K,V1]]] { override def map(from : TransformView[K,V1,V2,Tensor[K,V1]], fn : ((K,V2)=>V3)) = new TransformImpl[K,V1,V3,Tensor[K,V1]]( from.underlying, ((k:K, v:V1) => fn(k,from.transform(k,v)))); override def mapNonZero(from : TransformView[K,V1,V2,Tensor[K,V1]], fn : ((K,V2)=>V3)) = map(from, fn); } /** Override canMapValues on TensorView instances to construct a lazy view. */ implicit def mkIdentityCanMapValues[K, V1, V2:Scalar] = new CanMapValues[IdentityView[K,V1,Tensor[K,V1]],V1,V2,TransformView[K,V1,V2,Tensor[K,V1]]] { override def map(from : IdentityView[K,V1,Tensor[K,V1]], fn : (V1=>V2)) = new TransformImpl[K,V1,V2,Tensor[K,V1]](from.underlying, ((k:K,v:V1) => fn(v))); override def mapNonZero(from : IdentityView[K,V1,Tensor[K,V1]], fn : (V1=>V2)) = map(from, fn); } implicit def mkIdentityCanMapKeyValuePairs[K, V1, V2:Scalar] = new CanMapKeyValuePairs[IdentityView[K,V1,Tensor[K,V1]],K,V1,V2,TransformView[K,V1,V2,Tensor[K,V1]]] { override def map(from : IdentityView[K,V1,Tensor[K,V1]], fn : ((K,V1)=>V2)) = new TransformImpl[K,V1,V2,Tensor[K,V1]](from.underlying, fn); override def mapNonZero(from : IdentityView[K,V1,Tensor[K,V1]], fn : ((K,V1)=>V2)) = map(from, fn); } } ================================================ FILE: src/main/scala/scalala/tensor/Vector.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.IndexDomain; import scalala.generic.collection._; import dense.DenseVector; /** * Vectors are Tensor1s on the non-negative integers. * * @author dramage */ trait VectorLike[@specialized(Int,Long,Float,Double) V, +This<:Vector[V]] extends Tensor1Like[Int,V,IndexDomain,This] { self => /** Returns the number of elements in the domain of this vector. Same as size. */ def length : Int; override def size = length; override def domain = IndexDomain(length); override def foreachKey[U](fn : (Int => U)) = Range(0,size).foreach(fn); // // special case for comprehensions // /** Calls this.foreachValue(fn). */ def foreach[U](fn : (V=>U)) = this.foreachValue(fn); /** Calls this.mapValues(fn). */ def map[TT>:This,RV,That](fn : V => RV)(implicit bf : CanMapValues[TT, V, RV, That]) : That = this.mapValues[TT,RV,That](fn)(bf); def filter[TT>:This,That](f : V => Boolean)(implicit cf : CanBuildTensorFrom[TT,IndexDomain,Int,V,That]) = withFilter(f).strict; def withFilter(f : V => Boolean) = new Vector.Filtered[V,This](repr, f); /** Calls this.valuesIterator. */ def iterator : Iterator[V] = this.valuesIterator; // // Views // /** Returns a view of this vector as a row. */ def asRow : VectorRow[V] = this match { case r : VectorRow[_] => this.asInstanceOf[VectorRow[V]]; case _ => new VectorRow.View(repr); } /** Returns a view of this vector as a column. */ def asCol : VectorCol[V] = this match { case c : VectorCol[_] => this.asInstanceOf[VectorCol[V]]; case _ => new VectorCol.View(repr); } /** Returns a copy of this vector as a dense vector, preserving shape. */ def toDense : DenseVector[V]; /** Returns a copy of this vector's data as a list. */ def toList = List.tabulate(size)(i => this(i)); /** Returns a copy of this vector's data as a list. */ def toArray(implicit m : ClassManifest[V]) = Array.tabulate(size)(i => this(i)); } /** * Vectors are Tensor1's on the non-negative integers. * * @author dramage */ trait Vector[@specialized(Int,Long,Float,Double) V] extends Tensor1[Int,V] with VectorLike[V,Vector[V]]; object Vector { class Filtered[@specialized(Int,Long,Float,Double) V, +This<:Vector[V]] (inner : This, filterFn : V => Boolean) { def size = { var rv = 0; inner.foreach(v => if (filterFn(v)) rv += 1); rv; } def withFilter(fn : V => Boolean) = new Filtered[V,This](inner, v => filterFn(v) && fn(v)); def foreach[U](fn : V => U) = { for (v <- inner) if (filterFn(v)) fn(v); } def map[U,That](fn : V => U) (implicit bf : CanBuildTensorFrom[This,IndexDomain,Int,U,That]) = { val builder = bf(inner, IndexDomain(size)); var i = 0; for (v <- inner) { if (filterFn(v)) { builder(i) = fn(v); i += 1; } } builder.result; } // def flatMap[U,That](fn : V => Traversable[U]) // (implicit bf : CanBuildTensorFrom[This,IndexDomain,Int,U,That]) = { // val builder = bf(inner, IndexDomain(size)); // var i = 0; // for (v <- inner) { // if (filterFn(v)) { // for (u <- fn(v)) { // builder(i) = u; // i += 1; // } // } // } // builder.result; // } def strict[That](implicit bf : CanBuildTensorFrom[This,IndexDomain,Int,V,That]) = { val builder = bf(inner, IndexDomain(size)); var i = 0; for (v <- inner) { if (filterFn(v)) { builder(i) = v; i += 1; } } builder.result; } } } ================================================ FILE: src/main/scala/scalala/tensor/VectorCol.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import scalar.Scalar; import domain.IndexDomain; import scalala.generic.collection.{CanAppendColumns}; import scalala.operators._; import dense.{DenseVector,DenseVectorCol}; /** * Implementation trait for a row vector. * * @author dramage */ trait VectorColLike[@specialized(Int,Long,Float,Double) V, +This<:VectorCol[V]] extends VectorLike[V,This] with Tensor1ColLike[Int,V,IndexDomain,This] { override def t : VectorRow[V] = new VectorRow.View(repr); /** Returns a copy of this vector as a DenseVectorCol. */ override def toDense : DenseVectorCol[V] = { val rv = DenseVector.zeros(length); rv := repr; rv; } def toString(maxLines : Int = ScalalaConsole.terminalHeight - 3, mkValueString : V=>String = buildMkValueString) : String = { val showRows = if (length > maxLines) maxLines - 1 else length; val newline = System.getProperty("line.separator"); val rv = valuesIterator.take(showRows).map(mkValueString).mkString(newline); if (length > showRows) { rv + newline + "... ("+(domain.size) +" total)"; } else { rv; } } override def toString : String = toString(maxLines = ScalalaConsole.terminalHeight - 3, mkValueString = buildMkValueString); } /** * A vector shaped as a row. * * @author dramage */ trait VectorCol[@specialized(Int,Long,Float,Double) B] extends Vector[B] with Tensor1Col[Int,B] with VectorColLike[B,VectorCol[B]]; object VectorCol { class View[V](override val inner : Vector[V]) extends VectorProxy[V,Vector[V]] with VectorCol[V] with VectorLike[V,View[V]] { override def repr : View[V] = this; } // implicit def canAppendMatrixColumns[V] // : CanAppendColumns[Bound[V],Matrix[V],Matrix[V]] // = new CanAppendColumns[Bound[V],Matrix[V],Matrix[V]] { // override def apply(a : Bound[V], b : Matrix[V]) = { // require(a.size == b.numRows, "Arguments must have same number of rows"); // implicit val sv = a.scalar; // val builder = a.newBuilder[(Int,Int),V](TableDomain(a.size, 1+b.numCols)); // a.foreachNonZero((i,v) => builder((i,0)) = v); // b.foreachNonZero((i,j,v) => builder((i,j+1)) = v); // builder.result.asInstanceOf[Matrix[V]]; // } // } // implicit def canAppendVectorColumn[V] // : CanAppendColumns[Bound[V],VectorCol[V],Matrix[V]] // = new CanAppendColumns[Bound[V],VectorCol[V],Matrix[V]] { // override def apply(a : Bound[V], b : VectorCol[V]) = { // require(a.size == b.size, "Arguments must have same number of rows"); // implicit val sv = a.scalar; // val builder = a.newBuilder[(Int,Int),V](TableDomain(a.size, 2)); // a.foreachNonZero((i,v) => builder((i,0)) = v); // b.foreachNonZero((i,v) => builder((i,1)) = v); // builder.result.asInstanceOf[Matrix[V]]; // } // } } ================================================ FILE: src/main/scala/scalala/tensor/VectorProxy.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import domain.IndexDomain; /** * Implementation trait for proxies to a Vector instance. * * @author dramage */ trait VectorProxyLike[@specialized(Int,Long,Float,Double) V, Inner<:Vector[V], +This<:Vector[V]] extends Tensor1ProxyLike[Int,V,IndexDomain,Inner,This] with VectorLike[V,This] { override def length = inner.length; } /** * Proxy to a Vector instance. * * @author dramage */ trait VectorProxy[@specialized(Int,Long,Float,Double) V, Inner<:Vector[V]] extends Tensor1Proxy[Int,V,Inner] with Vector[V] with VectorProxyLike[V,Inner,VectorProxy[V,Inner]]; ================================================ FILE: src/main/scala/scalala/tensor/VectorRow.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import scalar.Scalar; import domain.IndexDomain; import generic.TensorBuilder; import scalala.generic.collection.{CanSliceCol}; import scalala.operators._; import dense.{DenseVector,DenseVectorRow}; /** * Implementation trait for a row vector. * * @author dramage */ trait VectorRowLike[@specialized(Int,Long,Float,Double) V, +This<:VectorRow[V]] extends VectorLike[V,This] with Tensor1RowLike[Int,V,IndexDomain,This] { override def t : VectorCol[V] = new VectorCol.View[V](repr); /** Returns a copy of this vector as a DenseVectorRow. */ override def toDense : DenseVectorRow[V] = { val rv = DenseVector.zeros(length).t; rv := repr; rv; } def toString(maxWidth : Int = ScalalaConsole.terminalWidth, mkValueString : V=>String = buildMkValueString) : String = { def colWidth(col : Int) = mkValueString(this(col)).length+2; val colWidths = new scala.collection.mutable.ArrayBuffer[Int]; var col = 0; while (col < size && colWidths.sum < maxWidth) { colWidths += colWidth(col); col += 1; } // make space for "... (K total)" if (colWidths.size < length) { while (colWidths.sum + maxWidth.toString.length + 12 >= maxWidth) { colWidths.remove(colWidths.length - 1); } } val newline = System.getProperty("line.separator"); var rv = new StringBuilder; for (col <- 0 until colWidths.length) { val cell = mkValueString(this(col)); rv.append(cell); rv.append(" " * (colWidths(col) - cell.length)); if (col == colWidths.length - 1) { if (col < size - 1) { rv.append("..."); rv.append(" ("); rv.append(length); rv.append(" total)"); } } } rv.append(newline); rv.toString; } override def toString = toString(maxWidth = ScalalaConsole.terminalWidth, mkValueString = buildMkValueString); } /** * A vector shaped as a row. * * @author dramage */ trait VectorRow[@specialized(Int,Long,Float,Double) V] extends Vector[V] with Tensor1Row[Int,V] with VectorRowLike[V,VectorRow[V]]; object VectorRow { class View[V](override val inner : Vector[V]) extends VectorProxy[V,Vector[V]] with VectorRow[V] with VectorLike[V,View[V]] { override def repr : View[V] = this; } } ================================================ FILE: src/main/scala/scalala/tensor/VectorSlice.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; import scalar.Scalar; import domain.{IterableDomain,IndexDomain}; /** * Implementation trait for a Vector view of a slice of keys from a Tensor. * * @author dramage */ trait VectorSliceLike [@specialized(Int,Long) K, +D<:IterableDomain[K], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K,V], +This<:VectorSlice[K,V,Coll]] extends Tensor1SliceLike[K, D, Int, IndexDomain, V, Coll, This] with VectorLike[V, This]; /** * A Vector view of a slice of keys from a Tensor. * * @author dramage */ trait VectorSlice [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K, V]] extends Tensor1Slice[K,Int,V,Coll] with Vector[V] with VectorSliceLike[K, IterableDomain[K], V, Coll, VectorSlice[K, V, Coll]]; object VectorSlice { abstract class FromKeySeq[K, V, +Coll <: Tensor[K, V]] (override val underlying : Coll, keys : Seq[K]) (implicit override val scalar : Scalar[V]) extends VectorSlice[K, V, Coll] { override def lookup(key : Int) = { checkKey(key); keys(key); } override def length = keys.size; } } /** * Implementation trait for a VectorRow view of a slice of keys from a Tensor. * * @author dramage */ trait VectorRowSliceLike [@specialized(Int,Long) K, +D<:IterableDomain[K], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K,V], +This<:VectorRowSlice[K,V,Coll]] extends VectorSliceLike[K, D, V, Coll, This] with VectorRowLike[V, This]; /** * A VectorRow view of a slice of keys from a Tensor. * * @author dramage */ trait VectorRowSlice [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K, V]] extends VectorSlice[K,V,Coll] with VectorRow[V] with VectorRowSliceLike[K, IterableDomain[K], V, Coll, VectorRowSlice[K, V, Coll]]; object VectorRowSlice { class FromKeySeq[K, V:Scalar, +Coll<:Tensor[K, V]](underlying : Coll, keys : Seq[K]) extends VectorSlice.FromKeySeq[K,V,Coll](underlying, keys) with VectorRowSlice[K,V,Coll] { override def toDense = { val rv = dense.DenseVectorRow.zeros[V](length); rv := repr; rv; } } } /** * Implementation trait for a VectorCol view of a slice of keys from a Tensor. * * @author dramage */ trait VectorColSliceLike [@specialized(Int,Long) K, +D<:IterableDomain[K], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K,V], +This<:VectorColSlice[K,V,Coll]] extends VectorSliceLike[K, D, V, Coll, This] with VectorColLike[V, This]; /** * A VectorCol view of a slice of keys from a Tensor. * * @author dramage */ trait VectorColSlice [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K, V]] extends VectorSlice[K,V,Coll] with VectorCol[V] with VectorColSliceLike[K, IterableDomain[K], V, Coll, VectorColSlice[K, V, Coll]]; object VectorColSlice { class FromKeySeq[K, V:Scalar, +Coll<:Tensor[K, V]](underlying : Coll, keys : Seq[K]) extends VectorSlice.FromKeySeq[K,V,Coll](underlying, keys) with VectorColSlice[K,V,Coll] { override def toDense = { val rv = dense.DenseVectorCol.zeros[V](length); rv := repr; rv; } } } ================================================ FILE: src/main/scala/scalala/tensor/dense/ArrayArrayMatrix.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package dense; import domain.TableDomain; import scalala.scalar.Scalar; /** * A matrix backed by an array of arrays of values. * Assumes row-major storage. * * @author dramage */ class ArrayArrayMatrix[B](val data : Array[Array[B]]) (implicit override val scalar : Scalar[B]) extends mutable.Matrix[B] with mutable.MatrixLike[B,ArrayArrayMatrix[B]] { if (data.map(_.length).distinct.size != 1) { throw new IllegalArgumentException("All rows must be same length"); } override def numRows = data.length; override def numCols = data(0).length; override def apply(i : Int, j : Int) = data(i)(j); override def update(i : Int, j : Int, v : B) = data(i)(j) = v; } ================================================ FILE: src/main/scala/scalala/tensor/dense/DenseArrayTensor.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package dense; import domain.{IterableDomain,IndexDomain,TableDomain}; import generic.TensorBuilder; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for a tensor backed by a dense array of values. * * @author dramage */ trait DenseArrayTensorLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +D<:IterableDomain[K], +This<:DenseArrayTensor[K,V]] extends mutable.TensorLike[K,V,D,This] { def data : Array[V]; override def newBuilder[K2,V2:Scalar](domain : IterableDomain[K2]) : TensorBuilder[K2,V2,Tensor[K2,V2]] = domain match { case that : IndexDomain => DenseVector.zeros[V2](that.size).asBuilder; case that : TableDomain => DenseMatrix.zeros[V2](that.numRows, that.numCols).asBuilder; case _ => super.newBuilder[K2,V2](domain); } override def foreachNonZeroValue[U](fn : (V=>U)) = { foreachValue(fn); true; } } /** * Mutable tensor backed by a dense array of values. * * @author dramage */ trait DenseArrayTensor [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V] extends mutable.Tensor[K,V] with DenseArrayTensorLike[K,V,IterableDomain[K],DenseArrayTensor[K,V]]; ================================================ FILE: src/main/scala/scalala/tensor/dense/DenseMatrix.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package dense; import domain.TableDomain; import scalala.generic.collection._; import scalala.scalar.Scalar; import scalala.library.random.MersenneTwisterFast; import scalala.operators._; import org.netlib.blas._; import org.netlib.lapack._; import org.netlib.util.intW import library.{LinearAlgebra, Random} ; /** * A DenseMatrix is backed by an array of doubles, with each column * stored before the next column begins. * * @author dramage */ @SerialVersionUID(1) class DenseMatrix[@specialized(Int,Long,Float,Double) V] (override val numRows : Int, override val numCols : Int, data_ : Array[V]) (implicit override val scalar : Scalar[V]) extends DenseArrayTensor[(Int,Int),V] with DenseArrayTensorLike[(Int,Int),V,TableDomain,DenseMatrix[V]] with mutable.Matrix[V] with mutable.MatrixLike[V,DenseMatrix[V]] with Serializable { override val data = data_ // workaround for https://lampsvn.epfl.ch/trac/scala/ticket/4013 if (numRows * numCols != data_.length) throw new IllegalArgumentException("data.length must equal numRows*numCols"); /** * Returns a view of this data matrix but with the given number of rows and columns. * * @throws IllegalArgumentException if the requested size does not match the current size. */ def reshape(rows : Int, cols : Int) : DenseMatrix[V] = { if (rows * cols != data.length) { throw new IllegalArgumentException("Cannot reshape "+numRows+"x"+numCols+" to "+rows+"x"+cols); } new DenseMatrix(rows, cols, data); } final def index(row : Int, col : Int) : Int = { checkKey(row,col); row + col * numRows; } final def unindex(index : Int) : (Int,Int) = (rowIndex(index), colIndex(index)); final def rowIndex(index : Int) : Int = (index % numRows); final def colIndex(index : Int) : Int = (index / numRows); override def apply(row : Int, col : Int) = data(index(row,col)); /** Special case DenseVectorRow slice. */ def apply(row : Int, cols : Range) = { checkKey(row,cols.last); new DenseVectorRow(data, offset = index(row,cols.head), stride = cols.step * numRows, length = cols.length) } /** Special case DenseVectorCol slice. */ def apply(rows : Range, col : Int) = { checkKey(rows.last,col); new DenseVectorCol(data, offset = index(rows.head,col), stride = rows.step, length = rows.length) } override def update(row : Int, col : Int, value : V) = data(index(row,col)) = value; override def foreachValue[U](f : (V)=>U) = { var i = 0; while (i < data.length) { f(data(i)); i += 1; } } override def foreachTriple[U](f : (Int,Int,V)=>U) = { var i = 0; while (i < data.length) { f(rowIndex(i),colIndex(i),data(i)); i += 1; } } /** Tranforms all values in this map by applying the given function. */ override def transformValues(f : V=>V) = { var i = 0; while (i < data.length) { data(i) = f(data(i)); i += 1; } } /** Tranforms all key value pairs in this map by applying the given function. */ override def transformTriples(f : (Int,Int,V)=>V) = { var i = 0; while (i < data.length) { data(i) = f(rowIndex(i),colIndex(i),data(i)); i += 1; } } def copy = new DenseMatrix[V](numRows, numCols, data.clone); } object DenseMatrix extends DenseMatrixConstructors { /** Any matrix multiplied by dense is dense. */ implicit def canBuildDenseMatrixMulRight[@specialized A, VA, VB, RV] (implicit viewA : A=>scalala.tensor.Matrix[VA], mul : BinaryOp[VA,VB,OpMul,RV], s : Scalar[RV]) : CanBuildTensorForBinaryOp[A,DenseMatrix[VB],TableDomain,(Int,Int),RV,OpMulMatrixBy,DenseMatrix[RV]] = new CanBuildTensorForBinaryOp[A,DenseMatrix[VB],TableDomain,(Int,Int),RV,OpMulMatrixBy,DenseMatrix[RV]] { override def apply(a : A, b : DenseMatrix[VB], domain : TableDomain) = DenseMatrix.zeros[RV](domain._1.size, domain._2.size).asBuilder. asInstanceOf[generic.TensorBuilder[(Int, Int),RV,DenseMatrix[RV]]]; } // // Capabilities // class DenseMatrixCanSliceRow[@specialized V:Scalar] extends CanSliceRow[DenseMatrix[V],Int,DenseVectorRow[V]] { override def apply(from : DenseMatrix[V], i : Int) = new DenseVectorRow[V](from.data, length = from.numCols, offset = i, stride = from.numRows); } class DenseMatrixCanSliceCol[@specialized V:Scalar] extends CanSliceCol[DenseMatrix[V],Int,DenseVectorCol[V]] { override def apply(from : DenseMatrix[V], j : Int) = new DenseVectorCol[V](from.data, length = from.numRows, offset = j * from.numRows, stride = 1); } class DenseMatrixCanMapValues[@specialized(Int,Long,Float,Double) V, @specialized(Int,Long,Float,Double) R:ClassManifest:Scalar] extends CanMapValues[DenseMatrix[V],V,R,DenseMatrix[R]] { override def map(from : DenseMatrix[V], fn : (V=>R)) = { val data = new Array[R](from.data.length); var i = 0; while (i < data.length) { data(i) = fn(from.data(i)); i += 1; } new DenseMatrix[R](from.numRows, from.numCols, data); } override def mapNonZero(from : DenseMatrix[V], fn : (V=>R)) = map(from, fn); } class DenseMatrixCanMapKeyValuePairs[@specialized(Int,Long,Float,Double) V, @specialized(Int,Long,Float,Double) R:ClassManifest:Scalar] extends CanMapKeyValuePairs[DenseMatrix[V],(Int,Int),V,R,DenseMatrix[R]] { override def map(from : DenseMatrix[V], fn : (((Int,Int),V)=>R)) = { val data = new Array[R](from.data.length); var i = 0; while (i < data.length) { data(i) = fn(from.unindex(i), from.data(i)); i += 1; } new DenseMatrix(from.numRows, from.numCols, data); } override def mapNonZero(from : DenseMatrix[V], fn : (((Int,Int),V)=>R)) = map(from, fn); } implicit def mkDenseMatrixCanSliceRow[@specialized V:Scalar] = new DenseMatrixCanSliceRow[V]; implicit def mkDenseMatrixCanSliceCol[@specialized V:Scalar] = new DenseMatrixCanSliceCol[V]; implicit def mkDenseMatrixCanMapValues[V,R:ClassManifest:Scalar] = new DenseMatrixCanMapValues[V,R]; implicit def mkDenseMatrixCanMapKeyValuePairs[V,R:ClassManifest:Scalar] = new DenseMatrixCanMapKeyValuePairs[V,R]; implicit object DenseMatrixCanSliceRowI extends DenseMatrixCanSliceRow[Int]; implicit object DenseMatrixCanSliceRowL extends DenseMatrixCanSliceRow[Long]; implicit object DenseMatrixCanSliceRowF extends DenseMatrixCanSliceRow[Float]; implicit object DenseMatrixCanSliceRowD extends DenseMatrixCanSliceRow[Double]; implicit object DenseMatrixCanSliceColI extends DenseMatrixCanSliceCol[Int]; implicit object DenseMatrixCanSliceColL extends DenseMatrixCanSliceCol[Long]; implicit object DenseMatrixCanSliceColF extends DenseMatrixCanSliceCol[Float]; implicit object DenseMatrixCanSliceColD extends DenseMatrixCanSliceCol[Double]; implicit object DenseMatrixCanMapValuesDD extends DenseMatrixCanMapValues[Double,Double]; implicit object DenseMatrixCanMapValuesII extends DenseMatrixCanMapValues[Int,Int]; implicit object DenseMatrixCanMapValuesID extends DenseMatrixCanMapValues[Int,Double]; // // BLAS and LAPACK routines // implicit object DenseMatrixDMulDenseMatrixD extends BinaryOp[DenseMatrix[Double],DenseMatrix[Double],OpMulMatrixBy,DenseMatrix[Double]] { def opType = OpMulMatrixBy; def apply(a : DenseMatrix[Double], b : DenseMatrix[Double]) = { val rv = DenseMatrix.zeros[Double](a.numRows, b.numCols); // System.err.println("BLAS!"); BLAS.getInstance().dgemm("n", "n", rv.numRows, rv.numCols, a.numCols, 1.0, a.data, a.numRows, b.data, a.numCols, 0.0, rv.data, a.numRows); rv; } } implicit object DenseMatrixDMulDenseVectorColD extends BinaryOp[DenseMatrix[Double],DenseVectorCol[Double],OpMulMatrixBy,DenseVectorCol[Double]] { def opType = OpMulMatrixBy; def apply(a : DenseMatrix[Double], b : DenseVectorCol[Double]) = { val rv = DenseVectorCol.zeros[Double](a.numRows); // System.err.println("BLAS!"); org.netlib.blas.Dgemv.dgemv("n", a.numRows, a.numCols, 1.0, a.data, 0, a.numRows, b.data, b.offset, b.stride, 0.0, rv.data, rv.offset, rv.stride); rv; } } implicit object DenseMatrixCanSolveDenseMatrix extends BinaryOp[DenseMatrix[Double],DenseMatrix[Double],OpSolveMatrixBy,DenseMatrix[Double]] { override def opType = OpSolveMatrixBy; override def apply(A : DenseMatrix[Double], V : DenseMatrix[Double]) = { require(A.numRows == V.numRows, "Non-conformant matrix sizes"); // from MTJ 0.9.9 if (A.numRows == A.numCols) { // square: LUSolve val X = V.copy; LUSolve(X,A); X; } else { // non-square: QRSolve val X = DenseMatrix.zeros[Double](A.numCols, V.numCols); QRSolve(X,A,V,false); X; } } /** X := A \ X */ def LUSolve(X : DenseMatrix[Double], A : DenseMatrix[Double]) = { val piv = new Array[Int](A.numRows); val info = new intW(0); LAPACK.getInstance().dgesv( A.numRows, X.numCols, A.data.clone(), math.max(1, A.numRows), piv, X.data, math.max(1, A.numRows), info); if (info.`val` > 0) throw new MatrixSingularException(); else if (info.`val` < 0) throw new IllegalArgumentException(); X; } /** X := A \ V */ def QRSolve(X : DenseMatrix[Double], A : DenseMatrix[Double], V : DenseMatrix[Double], transpose : Boolean) = { require(X.numRows == A.numCols, "Wrong number of rows in return value"); require(X.numCols == V.numCols, "Wrong number of rows in return value"); val nrhs = V.numCols; // allocate temporary solution matrix val Xtmp = DenseMatrix.zeros[Double](math.max(A.numRows, A.numCols), nrhs); val M = if (!transpose) A.numRows else A.numCols; for (j <- 0 until nrhs; i <- 0 until M) { Xtmp(i,j) = V(i,j); } val newData = A.data.clone(); // query optimal workspace val queryWork = new Array[Double](1); val queryInfo = new intW(0); LAPACK.getInstance().dgels( if (!transpose) "N" else "T", A.numRows, A.numCols, nrhs, newData, math.max(1,A.numRows), Xtmp.data, math.max(1,math.max(A.numRows,A.numCols)), queryWork, -1, queryInfo); // allocate workspace val work = { val lwork = { if (queryInfo.`val` != 0) math.max(1, math.min(A.numRows, A.numCols) + math.max(math.min(A.numRows, A.numCols), nrhs)); else math.max(queryWork(0).toInt, 1); } new Array[Double](lwork); } // compute factorization val info = new intW(0); LAPACK.getInstance().dgels( if (!transpose) "N" else "T", A.numRows, A.numCols, nrhs, newData, math.max(1,A.numRows), Xtmp.data, math.max(1,math.max(A.numRows,A.numCols)), work, work.length, info); if (info.`val` < 0) throw new IllegalArgumentException; // extract solution val N = if (!transpose) A.numCols else A.numRows; for (j <- 0 until nrhs; i <- 0 until N) X(i,j) = Xtmp(i,j); X; } } implicit object DenseMatrixCanSolveDenseVector extends BinaryOp[DenseMatrix[Double],DenseVectorCol[Double],OpSolveMatrixBy,DenseVectorCol[Double]] { override def opType = OpSolveMatrixBy; override def apply(a : DenseMatrix[Double], b : DenseVectorCol[Double]) = { val rv = a \ new DenseMatrix[Double](b.size, 1, b.data); new DenseVectorCol[Double](rv.data); } } } /** * Constructors for dense matrices. * * @author dramage */ trait DenseMatrixConstructors { /** Constructs a dense matrix for the given table domain. */ def apply[V:Scalar](domain : TableDomain) = zeros[V](domain._1.size, domain._2.size); /** Static constructor for a literal matrix. */ def apply[R,V](rows : R*)(implicit rl : LiteralRow[R,V], scalar : Scalar[V]) = { val nRows = rows.length; val nCols = rl.length(rows(0)); val rv = zeros(nRows, nCols); for ((row,i) <- rows.zipWithIndex) { rl.foreach(row, ((j, v) => rv(i,j) = v)); } rv; } /** Creates a dense matrix of the given value repeated of the requested size. */ def fill[V:Scalar](rows : Int, cols : Int)(value : V) = { implicit val mf = implicitly[Scalar[V]].manifest; new DenseMatrix[V](rows, cols, Array.fill(rows * cols)(value)); } /** Creates a dense matrix of zeros of the requested size. */ def zeros[V](rows : Int, cols : Int)(implicit s : Scalar[V]) = { if (s.isPrimitive) { new DenseMatrix(rows, cols, s.manifest.newArray(rows * cols)); } else { fill(rows, cols)(s.zero); } } /** Creates a dense matrix of zeros of the requested size. */ def ones[V:Scalar](rows : Int, cols : Int) = fill(rows, cols)(implicitly[Scalar[V]].one); /** Creates an identity matrix with size rows and columns. */ def eye[V](size : Int)(implicit scalar : Scalar[V]) = { val rv = zeros(size, size); for (i <- 0 until size) { rv(i,i) = scalar.one; } rv; } /** Creates a non-square "identity" matrix of the given size. */ def eye[V](rows : Int, cols : Int)(implicit scalar : Scalar[V]) = { val rv = zeros(rows, cols); for (i <- 0 until scala.math.min(rows, cols)) { rv(i, i) = scalar.one; } rv; } /** Tabulate a matrix from a function from row,col position to value. */ def tabulate[V:Scalar](rows : Int, cols : Int)(fn : (Int, Int) => V) = { implicit val mf = implicitly[Scalar[V]].manifest; new DenseMatrix(rows, cols, Array.tabulate(rows * cols)(i => fn(i % rows, i / rows))); } /** Horizontally tiles some matrices. They must have the same number of rows */ def horzcat[V:Scalar](matrices: Matrix[V]*) = { if(matrices.isEmpty) zeros[V](0,0) else { require(matrices.forall(m => m.numRows == matrices(0).numRows),"Not all matrices have the same number of rows"); val numCols = matrices.foldLeft(0)(_ + _.numCols); val numRows = matrices(0).numRows; val res = DenseMatrix.zeros[V](numRows,numCols); var offset = 0; for(m <- matrices) { res(0 until numRows,(offset) until (offset + m.numCols)) := m; offset+= m.numCols; } res } } /** Vertically tiles some matrices. They must have the same number of columns */ def vertcat[V:Scalar](matrices: Matrix[V]*) = { if(matrices.isEmpty) zeros[V](0,0) else { require(matrices.forall(m => m.numCols == matrices(0).numCols),"Not all matrices have the same number of columns"); val numRows = matrices.foldLeft(0)(_ + _.numRows); val numCols = matrices(0).numCols; val res = DenseMatrix.zeros[V](numRows,numCols); var offset = 0; for(m <- matrices) { res((offset) until (offset + m.numRows),0 until numCols) := m; offset+= m.numRows; } res } } /** A vector of the given size with uniform random values between 0 and 1. */ def rand(rows : Int, cols : Int, mt : MersenneTwisterFast = Random.mt) = mt.synchronized { tabulate(rows, cols)((i,j) => mt.nextDouble); } /** * A vector of the given size with normally distributed random values * with mean 0 and standard deviation 1. */ def randn(rows : Int, cols : Int, mt : MersenneTwisterFast = Random.mt) = mt.synchronized { tabulate(rows, cols)((i,j) => mt.nextGaussian); } /** A vector of the given size of random integers in the range [0..max). */ def randi(imax : Int, rows : Int, cols : Int, mt : MersenneTwisterFast = Random.mt) = mt.synchronized { tabulate(rows, cols)((i,j) => mt.nextInt(imax)); } /** * Computes a matrix whose columns represent samples drawn from a multivariate * Gaussian distribution obeying both the given mean `mu' and covariance * matrix `Sigma'. * * @throws NotConvergedException in case of a malformed covariance matrix */ def randn(mu: Vector[Double], sigma: Matrix[Double], numSamples: Int)(implicit mt : MersenneTwisterFast): DenseMatrix[Double] = { require(numSamples >= 1, "Must request at least one sample"); require(sigma.isSymmetric, "Sigma must be symmetric"); require(mu.size == sigma.numCols, "mu must be same length as sigma"); // Assuming multivariate samples with zero mean, the general form of // the covariance matrix is X X^T where the scale factor 1/(N-1) has // been left out for improved readabilty. // Let Y = AX, then Y Y^T = (AX) (AX)^T = A (X X^T) A^T. // In case of a random matrix X where each element of X has been // drawn from a standard normal distribution, and where thus all // random variables are i.i.d. it holds that X X^T = I (identity) // yielding A (X X^T) A^T = A A^T. // So we're looking for a "square root" A of the given covariance // matrix Sigma: val sqrtSigma = LinearAlgebra.cholesky(sigma) val samples: DenseMatrix[Double] = sqrtSigma * DenseMatrix.randn(mu.size, numSamples, mt) // Due to the row-major storage order of (dense) matrices it's probably // best to use row-wise scalar addition instead of column-wise vector // addition: for (i <- 0 until mu.size) samples(i, ::) += mu(i) samples } } ================================================ FILE: src/main/scala/scalala/tensor/dense/DenseVector.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package dense; import domain.{IterableDomain,IndexDomain}; import scalala.generic.collection._; import scalala.scalar.Scalar; import scalala.library.random.MersenneTwisterFast; import scalala.library.Random; import scalala.operators._ import bundles.MutableInnerProductSpace import java.util.Arrays /** * A vector backed by a dense array. * * @author dramage */ @SerialVersionUID(1) trait DenseVector[@specialized(Int,Long,Float,Double) V] extends mutable.Vector[V] with mutable.VectorLike[V,DenseVector[V]] with DenseArrayTensor[Int,V] with DenseArrayTensorLike[Int,V,IndexDomain,DenseVector[V]] { self => /** Starting offset within data array. */ val offset : Int; /** Gap between successive elements in data array. */ val stride : Int; override def apply(key : Int) = data(offset + key * stride); override def update(key : Int, value : V) = data(offset + key * stride) = value; override def foreachPair[U](fn : ((Int,V)=>U)) = { var i = 0; var k = offset; while (i < length) { fn(i, data(k)); i += 1; k += stride; } } override def foreachValue[U](fn : (V=>U)) = { var i = 0; var k = offset; while (i < length) { fn(data(k)); i += 1; k += stride; } } override def transformPairs(fn : (Int,V)=>V) = { var i = 0; var k = offset; while (i < length) { data(k) = fn(i,data(k)); i += 1; k += stride; } } override def transformValues(fn : V=>V) = { var i = 0; var k = offset; while (i < length) { data(k) = fn(data(k)); i += 1; k += stride; } } /** Returns a view of this vector as a row. */ override def asRow : DenseVectorRow[V] = new DenseVectorRow(this.data, offset, stride, length); /** Returns a view of this vector as a column. */ override def asCol : DenseVectorCol[V] = new DenseVectorCol(this.data, offset, stride, length); } trait LowPriorityDenseImplicits { class CanJoinDenseWithNonDense[ @specialized(Int,Long,Float,Double) V1, @specialized(Int,Long,Float,Double) V2, DV[V]<:DenseVector[V]] extends CanJoin[DV[V1], Vector[V2], Int, V1, V2] { def joinAll[RV](a: DV[V1], b: Vector[V2], fn: (Int, V1, V2) => RV) { a.checkDomain(b.domain) for( (i,v2) <- b.pairs) { fn(i,a(i),v2) } } def joinBothNonZero[RV](a: DV[V1], b: Vector[V2], fn: (Int, V1, V2) => RV) { joinAll(a,b,fn) } def joinEitherNonZero[RV](a: DV[V1], b: Vector[V2], fn: (Int, V1, V2) => RV) { joinAll(a,b,fn) } } /** Optimized base class for joining dense columns. */ implicit def canJoinDenseVectorColsWithNonDense[V1, V2] : CanJoinDenseWithNonDense[V1, V2, DenseVectorCol] = new CanJoinDenseWithNonDense[V1, V2, DenseVectorCol]; /** Optimized base class for joining dense rows. */ implicit def canJoinDenseVectorRowsWithNonDense[V1, V2] : CanJoinDenseWithNonDense[V1, V2, DenseVectorRow] = new CanJoinDenseWithNonDense[V1, V2, DenseVectorRow]; } object DenseVector extends DenseVectorConstructors with LowPriorityDenseImplicits { // // Generic optimized routines // class GenericDenseVectorRowBase[@specialized V:Scalar:Manifest] { def create(length : Int) = new DenseVectorRow(new Array[V](length)); } class GenericDenseVectorColBase[@specialized V:Scalar:Manifest] { def create(length : Int) = new DenseVectorCol(new Array[V](length)); } class GenericDenseVectorBase[@specialized V:Scalar:Manifest] { def create(length : Int) = new DenseVectorCol(new Array[V](length)); } /** Optimized base class for joining two dense tensors. */ class CanJoinDenseVectors[ @specialized(Int,Long,Float,Double) V1, @specialized(Int,Long,Float,Double) V2, DV[V]<:DenseVector[V]] extends CanJoin[DV[V1], DV[V2], Int, V1, V2] { override def joinAll[RV](a : DV[V1], b : DV[V2], fn : (Int,V1,V2)=>RV) = { // System.err.println("DENSE!"); a.checkDomain(b.domain); var i = 0; var k1 = a.offset; var k2 = b.offset; while (i < a.length) { fn(i, a.data(k1), b.data(k2)); i += 1; k1 += a.stride; k2 += b.stride; } } override def joinBothNonZero[RV](a : DV[V1], b : DV[V2], fn : (Int,V1,V2)=>RV) = joinAll(a,b,fn); override def joinEitherNonZero[RV](a : DV[V1], b : DV[V2], fn : (Int,V1,V2)=>RV) = joinAll(a,b,fn); } /** Optimized base class for joining dense columns. */ implicit def canJoinDenseVectorCols[V1, V2] : CanJoinDenseVectors[V1, V2, DenseVectorCol] = new CanJoinDenseVectors[V1, V2, DenseVectorCol]; /** Optimized base class for joining dense rows. */ implicit def canJoinDenseVectorRows[V1, V2] : CanJoinDenseVectors[V1, V2, DenseVectorRow] = new CanJoinDenseVectors[V1, V2, DenseVectorRow]; /** Optimized base class for mapping a dense tensor. */ trait CanMapValuesDenseVector [@specialized V, @specialized RV, DV[V]<:DenseVector[V]] extends CanMapValues[DV[V],V,RV,DV[RV]] { def create(length : Int) : DV[RV]; override def map(from : DV[V], fn : (V=>RV)) = { // System.err.println("DENSE!"); val rv = create(from.length); var i = 0; var k = from.offset; while (i < from.length) { rv.data(i) = fn(from.data(k)); i += 1; k += from.stride; } rv; } override def mapNonZero(from : DV[V], fn : (V=>RV)) = map(from, fn); } /** Optimized base class for mapping dense columns. */ implicit def canMapValuesDenseVectorCols[@specialized V, @specialized RV:Scalar:Manifest] : CanMapValuesDenseVector[V, RV, DenseVectorCol] = new GenericDenseVectorColBase with CanMapValuesDenseVector[V, RV, DenseVectorCol]; /** Optimized base class for mapping dense rows. */ implicit def canMapValuesDenseVectorRows[@specialized V, @specialized RV:Scalar:Manifest] : CanMapValuesDenseVector[V, RV, DenseVectorRow] = new GenericDenseVectorRowBase with CanMapValuesDenseVector[V, RV, DenseVectorRow]; /** optimized for just mapping densevectors */ implicit def canMapValuesDenseVectors[@specialized V, @specialized RV:Scalar:Manifest] : CanMapValuesDenseVector[V, RV, DenseVector] = new GenericDenseVectorColBase with CanMapValuesDenseVector[V, RV, DenseVector]; /** Optimized base class for mapping a dense tensor. */ trait CanZipMapValuesDenseVector [@specialized V, @specialized RV, DV[V]<:DenseVector[V]] extends CanZipMapValues[DV[V],V,RV,DV[RV]] { def create(length : Int) : DV[RV]; /**Maps all corresponding values from the two collection. */ def map(from: DV[V], from2: DV[V], fn: (V, V) => RV) = { require(from.length == from2.length, "Vector lengths must match!") val result = create(from.length) var i = 0 while (i < from.length) { result(i) = fn(from(i), from2(i)) i += 1 } result } } /** Optimized base class for mapping dense columns. */ implicit def canZipMapValuesDenseVectorCols[@specialized V, @specialized RV:Scalar:Manifest] : CanZipMapValuesDenseVector[V, RV, DenseVectorCol] = new GenericDenseVectorColBase with CanZipMapValuesDenseVector[V, RV, DenseVectorCol]; /** Optimized base class for mapping dense rows. */ implicit def canZipMapValuesDenseVectorRows[@specialized V, @specialized RV:Scalar:Manifest] : CanZipMapValuesDenseVector[V, RV, DenseVectorRow] = new GenericDenseVectorRowBase with CanZipMapValuesDenseVector[V, RV, DenseVectorRow]; /** optimized for just mapping densevectors */ implicit def canZipMapValuesDenseVectors[@specialized V, @specialized RV:Scalar:Manifest] : CanZipMapValuesDenseVector[V, RV, DenseVector] = new GenericDenseVectorColBase with CanZipMapValuesDenseVector[V, RV, DenseVector]; /** Optimized base class for mapping a dense tensor. */ trait CanMapKeyValuePairsDenseVector [@specialized V, @specialized RV, DV[V]<:DenseVector[V]] extends CanMapKeyValuePairs[DV[V],Int,V,RV,DV[RV]] { def create(length : Int) : DV[RV]; override def map(from : DV[V], fn : (Int,V)=>RV) = { // System.err.println("DENSE!"); val rv = create(from.length); var i = 0; var k = from.offset; while (i < from.length) { rv.data(i) = fn(i, from.data(k)); i += 1; k += from.stride; } rv; } override def mapNonZero(from : DV[V], fn : (Int,V)=>RV) = map(from, fn); } /** Optimized base class for mapping dense columns. */ implicit def canMapKeyValuePairsDenseVectorCols[@specialized V, @specialized RV:Scalar:Manifest] : CanMapKeyValuePairsDenseVector[V, RV, DenseVectorCol] = new GenericDenseVectorColBase with CanMapKeyValuePairsDenseVector[V, RV, DenseVectorCol]; /** Optimized base class for mapping dense rows. */ implicit def canMapKeyValuePairsDenseVectorRows[@specialized V, @specialized RV:Scalar:Manifest] : CanMapKeyValuePairsDenseVector[V, RV, DenseVectorRow] = new GenericDenseVectorRowBase with CanMapKeyValuePairsDenseVector[V, RV, DenseVectorRow]; implicit def canMapKeyValuePairsDenseVector[@specialized V, @specialized RV:Scalar:Manifest] : CanMapKeyValuePairsDenseVector[V, RV, DenseVector] = new GenericDenseVectorColBase with CanMapKeyValuePairsDenseVector[V, RV, DenseVector]; /** Optimized base class for creating zeros */ trait CanCreateZerosDenseVector [@specialized V, @specialized RV, DV[V]<:DenseVector[V]] extends CanCreateZerosLike[DV[V],DV[RV]] { def create(length : Int) : DV[RV]; def apply(v1: DV[V]) = create(v1.length); } implicit def canCreateZerosDenseVector[@specialized V, @specialized RV:Scalar:Manifest] : CanCreateZerosDenseVector[V, RV, DenseVector] = new GenericDenseVectorColBase with CanCreateZerosDenseVector[V, RV, DenseVector]; /** Optimized base class for mapping dense columns. */ implicit def canCreateZerosDenseVectorCols[@specialized V, @specialized RV:Scalar:Manifest] : CanCreateZerosDenseVector[V, RV, DenseVectorCol] = new GenericDenseVectorColBase with CanCreateZerosDenseVector[V, RV, DenseVectorCol]; /** Optimized base class for mapping dense rows. */ implicit def canCreateZerosDenseVectorRows[@specialized V, @specialized RV:Scalar:Manifest] : CanCreateZerosDenseVector[V, RV, DenseVectorRow] = new GenericDenseVectorRowBase with CanCreateZerosDenseVector[V, RV, DenseVectorRow]; /** Optimized base class for copying zeros */ class CanCopyDenseVectorRow[@specialized V:Scalar:ClassManifest] extends CanCopy[DenseVectorRow[V]] { def apply(v1: DenseVectorRow[V]) = { new DenseVectorRow(Array.tabulate(v1.length)(i => v1(i))); } } class CanCopyDenseVector[@specialized V:Scalar:ClassManifest] extends CanCopy[DenseVector[V]] { def apply(v1: DenseVector[V]) = { new DenseVectorCol(Array.tabulate(v1.length)(i => v1(i))); } } class CanCopyDenseVectorCol[@specialized V:Scalar:ClassManifest] extends CanCopy[DenseVectorCol[V]] { def apply(v1: DenseVectorCol[V]) = { new DenseVectorCol(Array.tabulate(v1.length)(i => v1(i))); } } /** Optimized base class for mapping dense columns. */ implicit def canCopyDenseVectorCols[@specialized V:Scalar:Manifest] = new CanCopyDenseVectorCol[V]; /** Optimized base class for mapping dense rows. */ implicit def canCopyDenseVectorRows[@specialized V:Scalar:Manifest] = new CanCopyDenseVectorRow[V]; // // Specialized objects for generic routines // implicit object CanJoinDVCDDVCD extends CanJoinDenseVectors[Double,Double,DenseVectorCol]; implicit object CanJoinDVRDDVRD extends CanJoinDenseVectors[Double,Double,DenseVectorRow]; implicit object CanMapValuesDV extends GenericDenseVectorBase[Double] with CanMapValuesDenseVector[Double,Double,DenseVector]; implicit object CanMapValuesDVCDDVCD extends GenericDenseVectorColBase[Double] with CanMapValuesDenseVector[Double,Double,DenseVectorCol]; implicit object CanMapValuesDVRDDVRD extends GenericDenseVectorRowBase[Double] with CanMapValuesDenseVector[Double,Double,DenseVectorRow]; implicit object CanMapKeyValuePairsDVCDDVCD extends GenericDenseVectorColBase[Double] with CanMapKeyValuePairsDenseVector[Double,Double,DenseVectorCol]; implicit object CanMapKeyValuePairsDVRDDVRD extends GenericDenseVectorRowBase[Double] with CanMapKeyValuePairsDenseVector[Double,Double,DenseVectorRow]; // // BLAS routines // /** BLAS-optimized scala multiply. */ implicit object DenseVectorDMulDInto extends BinaryUpdateOp[DenseVector[Double],Double,OpMul] { override def opType = OpMul; override def apply(a : DenseVector[Double], b : Double) = { // System.err.println("BLAS!"); org.netlib.blas.Dscal.dscal(a.length, b, a.data, a.offset, a.stride); } } /** BLAS-optimized vector addition. */ implicit object DenseVectorDAddDenseVectorDInto extends BinaryUpdateOp[DenseVector[Double],DenseVector[Double],OpAdd] { override def opType = OpAdd; override def apply(a : DenseVector[Double], b : DenseVector[Double]) = { require(a.length == b.length, "Vectors must have same length"); // System.err.println("BLAS!"); org.netlib.blas.Daxpy.daxpy( a.length, 1.0, b.data, b.offset, b.stride, a.data, a.offset, a.stride); } } /** BLAS-optimized vector subtraction. */ implicit object DenseVectorDSubDenseVectorDInto extends BinaryUpdateOp[DenseVector[Double],DenseVector[Double],OpSub] { override def opType = OpSub; override def apply(a : DenseVector[Double], b : DenseVector[Double]) = { require(a.length == b.length, "Vectors must have same length"); // System.err.println("BLAS!"); org.netlib.blas.Daxpy.daxpy( a.length, -1.0, b.data, b.offset, b.stride, a.data, a.offset, a.stride); } } /** BLAS-optimized vector-vector inner product. */ implicit object DenseVectorDInnerMulDenseVectorD extends BinaryOp[DenseVectorRow[Double],DenseVectorCol[Double],OpMulRowVectorBy,Double] { override def opType = OpMulRowVectorBy; override def apply(a : DenseVectorRow[Double], b : DenseVectorCol[Double]) = { require(a.length == b.length, "Vectors must have same length"); // System.err.println("BLAS!"); org.netlib.blas.Ddot.ddot( a.length, a.data, a.offset, a.stride, b.data, b.offset, b.stride); } } /** BLAS-optimized forwarding calls from UpdateOp to Op */ implicit def binaryOpFromBinaryUpdateOp[DV<:DenseVector[Double],Other,Op<:OpType](implicit copy: CanCopy[DV], op: BinaryUpdateOp[DV,Other,Op]) = { new BinaryOp[DV,Other,Op,DV] { override def opType = op.opType; override def apply(a : DV, b : Other) = { val c = copy(a) op(c,b) c } } } implicit def denseVectorColVSpace:MutableInnerProductSpace[Double,DenseVectorCol[Double]] = { MutableInnerProductSpace.make[Double,DenseVectorCol[Double]] }; implicit def denseVectorRowVSpace:MutableInnerProductSpace[Double,DenseVectorRow[Double]] = { MutableInnerProductSpace.make[Double,DenseVectorRow[Double]] }; implicit def denseVectorVSpace:MutableInnerProductSpace[Double,DenseVector[Double]] = { MutableInnerProductSpace.make[Double,DenseVector[Double]] }; } /** * DenseVectors as a row. * * @author dramage */ final class DenseVectorRow[@specialized(Int,Long,Float,Double) V] (override final val data : Array[V], override final val offset : Int, override val stride : Int, override val length : Int) (implicit override val scalar : Scalar[V]) extends DenseVector[V] with mutable.VectorRow[V] with mutable.VectorRowLike[V,DenseVectorRow[V]] { def this(data : Array[V])(implicit s : Scalar[V]) = this(data, 0, 1, data.length)(s); // we have this pointless override to encourage hotspot to inline @inline override def apply(key: Int) = data(offset + key * stride); def apply(range : Range) : DenseVectorRow[V] = { if(range.isEmpty) DenseVectorRow.zeros[V](0) else { require(range.last < length, "Range out of bounds"); new DenseVectorRow[V](data, offset = offset + stride * range.start, stride = stride * range.step, length = range.size); } } override def newBuilder[K2,V2:Scalar](domain : IterableDomain[K2]) = { implicit val mf = implicitly[Scalar[V2]].manifest; domain match { case that : IndexDomain => new DenseVectorRow(new Array[V2](that.size)).asBuilder; case _ => super.newBuilder[K2,V2](domain); } } override def t : DenseVectorCol[V] = new DenseVectorCol(data, offset, stride, length)(scalar); // Override asRow to avoid unnecessary copies. @inline override def asRow: DenseVectorRow[V] = this } /** * DenseVector as a column. * * @author dramage */ final class DenseVectorCol[@specialized(Int,Long,Float,Double) V] (override val data : Array[V], override val offset : Int, override val stride : Int, override val length : Int) (implicit override val scalar : Scalar[V]) extends DenseVector[V] with mutable.VectorCol[V] with mutable.VectorColLike[V,DenseVectorCol[V]] with Serializable { def this(data : Array[V])(implicit s : Scalar[V]) = this(data, 0, 1, data.length)(s); // we have this pointless override to encourage hotspot to inline @inline override def apply(key: Int) = data(offset + key * stride); def apply(range : Range) : DenseVectorCol[V] = { if(range.isEmpty) DenseVectorCol.zeros[V](0) else { require(range.last < length, "Range out of bounds"); new DenseVectorCol[V](data, offset = offset + stride * range.start, stride = stride * range.step, length = range.size); } } override def newBuilder[K2,V2:Scalar](domain : IterableDomain[K2]) = { implicit val mf = implicitly[Scalar[V2]].manifest; domain match { case that : IndexDomain => new DenseVectorCol(new Array[V2](that.size)).asBuilder; case _ => super.newBuilder[K2,V2](domain); } } override def t : DenseVectorRow[V] = new DenseVectorRow(data, offset, stride, length)(scalar); // Override asCol to avoid unnecessary copies. @inline override def asCol: DenseVectorCol[V] = this } /** * Common constructors shared by DenseVectorRow and DenseVectorCol. * @author dramage, afwlehmann * */ trait CommonDenseVectorConstructors [+This[_] <: DenseVector[_]] { /** * Constructs a DenseVector from the given values. */ def apply[@specialized V: Scalar](values: Array[V]): This[V] /** * Constructs a DenseVector from the given values. */ def apply[@specialized V: Scalar](values: V*): This[V] = { implicit val mf = implicitly[Scalar[V]].manifest apply(values.toArray) } /** * Constructs a DenseVector for the given IndexDomain. */ def apply[@specialized V: Scalar](domain: IndexDomain): This[V] = zeros(domain.size) /** * Dense vector containing the given value for all elements. */ def fill[V: Scalar](size: Int)(value: V): This[V] = { implicit val mf = implicitly[Scalar[V]].manifest // this is too slow: apply(Array.fill(size)(value)) if(mf.getClass.isAssignableFrom(java.lang.Double.TYPE)) { val arr = new Array[V](size) Arrays.fill(arr.asInstanceOf[Array[Double]],value.asInstanceOf[Double]) apply(arr) } else if(mf.getClass.isAssignableFrom(java.lang.Float.TYPE)) { val arr = new Array[V](size) Arrays.fill(arr.asInstanceOf[Array[Float]],value.asInstanceOf[Float]) apply(arr) } else if(mf.getClass.isAssignableFrom(java.lang.Integer.TYPE)) { val arr = new Array[V](size) Arrays.fill(arr.asInstanceOf[Array[Int]],value.asInstanceOf[Int]) apply(arr) } else if(mf.getClass.isAssignableFrom(java.lang.Long.TYPE)) { val arr = new Array[V](size) Arrays.fill(arr.asInstanceOf[Array[Long]],value.asInstanceOf[Long]) apply(arr) } else { apply(Array.fill(size)(value)) } } /** * DenseVector of zeros of the given size. */ def zeros[V](size: Int)(implicit s: Scalar[V]): This[V] = { if (s.isPrimitive) apply(s.manifest.newArray(size)) else fill(size)(s.zero) } /** * DenseVector of ones of the given size. */ def ones[V: Scalar](size: Int): This[V] = fill(size)(implicitly[Scalar[V]].one) /** * Tabulate a DenseVector with the value at each offset given by the function. */ def tabulate[V: Scalar](size: Int)(f: (Int => V)): This[V] = { implicit val mf = implicitly[Scalar[V]].manifest apply(Array.tabulate(size)(f)) } /** * Returns a vector with numbers from 'from' up to (but not including) * 'until' incrementing by 'by' at each step. */ def range(from: Int, until: Int, by: Int = 1): This[Int] = apply[Int](Array.range(from, until, by)) /** * A vector of the given size with uniform random values from [0,1). */ def rand(size: Int, mt: MersenneTwisterFast = Random.mt): This[Double] = mt.synchronized { tabulate(size)(i => mt.nextDouble) } /** * A vector of the given size with normally distributed random values * with mean 0 and standard deviation 1. */ def randn(size: Int, mt: MersenneTwisterFast = Random.mt): This[Double] = mt.synchronized { tabulate(size)(i => mt.nextGaussian) } /** * A vector of the given size of random integers in the range [0..max). */ def randi(imax: Int, size: Int, mt: MersenneTwisterFast = Random.mt): This[Int] = mt.synchronized { tabulate(size)(i => mt.nextInt(imax)) } } /** * @author dramage, afwlehmann */ object DenseVectorRow extends CommonDenseVectorConstructors[DenseVectorRow] { /** * {@inheritDoc} */ override def apply[@specialized V: Scalar](values: Array[V]): DenseVectorRow[V] = new DenseVectorRow[V](values) /** * Horizontal concatenation of two or more row vectors into one large vector. */ def horzcat[V: Scalar](vectors: VectorRow[V]*): DenseVectorRow[V] = { val size = vectors.foldLeft(0)(_ + _.size) val result = zeros[V](size) var offset = 0 for (v <- vectors) { result(offset until (offset + v.size)) := v offset += v.size } result } /** * Vertical concatenation of two or more row vectors into one matrix. * @throws IllegalArgumentException if vectors have different sizes */ def vertcat[V: Scalar](vectors: VectorRow[V]*): DenseMatrix[V] = { val size = vectors.head.size if (!(vectors forall (_.size == size))) throw new IllegalArgumentException("All vectors must have the same size!") val result = DenseMatrix.zeros[V](vectors.size, size) for ((v, row) <- vectors zip (0 until vectors.size)) result(row,::) := v result } } /** * @author dramage, afwlehmann */ trait DenseVectorColConstructors extends CommonDenseVectorConstructors[DenseVectorCol] { /** * {@inheritDoc} */ override def apply[@specialized V: Scalar](values: Array[V]): DenseVectorCol[V] = new DenseVectorCol[V](values) /** * Horizontal concatenation of two or more row vectors into one matrix. * @throws IllegalArgumentException if vectors have different sizes */ def horzcat[V: Scalar](vectors: VectorCol[V]*): DenseMatrix[V] = { val size = vectors.head.size if (!(vectors forall (_.size == size))) throw new IllegalArgumentException("All vectors must have the same size!") val result = DenseMatrix.zeros[V](vectors.size, size) for ((v, col) <- vectors zip (0 until vectors.size)) result(::,col) := v result } /** * Vertical concatenation of two or more column vectors into one large vector. */ def vertcat[V: Scalar](vectors: VectorCol[V]*): DenseVectorCol[V] = { val size = vectors.foldLeft(0)(_ + _.size) val result = zeros[V](size) var offset = 0 for (v <- vectors) { result(offset until (offset + v.size)) := v offset += v.size } result } } object DenseVectorCol extends DenseVectorColConstructors trait DenseVectorConstructors extends DenseVectorColConstructors ================================================ FILE: src/main/scala/scalala/tensor/domain/CanBuildDomain2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * Marker trait for statically building a Domain2 for two input domains. * * @author dramage */ trait CanBuildDomain2[-A,-B,RV] extends ((A,B) => RV); trait CanBuildDomain2ImplicitsLevel0 { implicit def buildGeneral[K1,K2] : CanBuildDomain2[Domain1[K1],Domain1[K2],Domain2[K1,K2]] = new CanBuildDomain2[Domain1[K1],Domain1[K2],Domain2[K1,K2]] { def apply(a : Domain1[K1], b : Domain1[K2]) = a.product[K2,Domain1[K2]](b); } } trait CanBuildDomain2ImplicitsLevel1 extends CanBuildDomain2ImplicitsLevel0 { implicit object BuildIndexIndex extends CanBuildDomain2[IndexDomain,IndexDomain,TableDomain] { override def apply(a : IndexDomain, b : IndexDomain) = TableDomain(a.size, b.size); } } object CanBuildDomain2 extends CanBuildDomain2ImplicitsLevel1; ================================================ FILE: src/main/scala/scalala/tensor/domain/CanGetDomain.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * Marker trait for statically getting the domain of a given tensor. * * @author dramage */ trait CanGetDomain[-From,Domain] extends (From => Domain); trait CanGetDomainImplicitsLevel0 { implicit def domainForTensor[K,T](implicit view : T => Tensor[K,_]) : CanGetDomain[T,IterableDomain[K]] = new CanGetDomain[T,IterableDomain[K]] { def apply(t : T) = t.domain; } } trait CanGetDomainImplicitsLevel1 extends CanGetDomainImplicitsLevel0 { implicit def domainForTensor1[K,T](implicit view : T => Tensor1[K,_]) : CanGetDomain[T,Domain1[K]] = new CanGetDomain[T,Domain1[K]] { def apply(t : T) = t.domain; } implicit def domainForTensor2[K1,K2,T](implicit view : T => Tensor2[K1,K2,_]) : CanGetDomain[T,Domain2[K1,K2]] = new CanGetDomain[T,Domain2[K1,K2]] { def apply(t : T) = t.domain; } } trait CanGetDomainImplicitsLevel2 extends CanGetDomainImplicitsLevel1 { implicit def domainForVector[T](implicit view : T => Vector[_]) : CanGetDomain[T,IndexDomain] = new CanGetDomain[T,IndexDomain] { def apply(t : T) = t.domain; } implicit def domainForMatrix[T](implicit view : T => Matrix[_]) = new CanGetDomain[T,TableDomain] { def apply(t : T) = t.domain; } } object CanGetDomain extends CanGetDomainImplicitsLevel2 { def apply[T] = new { def apply[D](implicit df : CanGetDomain[T,D]) = df; } } /** * Capability trait for statically getting the domain2 of a Tensor2. * * @author dramage */ trait CanGetDomain2[-From,D1,D2,Domain] extends (From => Domain) { def _1(from : From) : D1; def _2(from : From) : D2; } trait CanGetDomain2ImplicitsLevel0 { implicit def domainForTensor2[K1,K2,T](implicit view : T => Tensor2[K1,K2,_]) : CanGetDomain2[T,Domain1[K1],Domain1[K2],Domain2[K1,K2]] = new CanGetDomain2[T,Domain1[K1],Domain1[K2],Domain2[K1,K2]] { def apply(t : T) = t.domain; def _1(t : T) = t.domain._1; def _2(t : T) = t.domain._2; } } trait CanGetDomain2ImplicitsLevel1 extends CanGetDomain2ImplicitsLevel0 { implicit def domainForMatrix[T](implicit view : T => Matrix[_]) : CanGetDomain2[T,IndexDomain,IndexDomain,TableDomain] = new CanGetDomain2[T,IndexDomain,IndexDomain,TableDomain] { def apply(t : T) = t.domain; def _1(t : T) = t.domain._1; def _2(t : T) = t.domain._2; } } object CanGetDomain2 extends CanGetDomain2ImplicitsLevel1 { def apply[T] = new { def apply[D1,D2,D](implicit df : CanGetDomain2[T,D1,D2,D]) = df; } } ================================================ FILE: src/main/scala/scalala/tensor/domain/Domain.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * Implementation trait for domains of a DomainFunction, representing * a restriction on values of type A. * * @author dramage */ trait DomainLike[@specialized(Int,Long,Float,Double) A, +This<:Domain[A]] extends (A => Boolean) { def repr : This = this.asInstanceOf[This]; /** Calls contains(key). */ final override def apply(key : A) = contains(key); /** Returns true if the given element is part of the set. */ def contains(key : A) : Boolean; } /** * Domains of a DomainFunction, representing a restriction on values of type A. * * @author dramage */ trait Domain[@specialized(Int,Long,Float,Double) A] extends DomainLike[A, Domain[A]]; /** * An exception thrown when encountering an invalid domain. * * @author dramage */ class DomainException(msg : String) extends RuntimeException(msg) { def this() = this(null); } ================================================ FILE: src/main/scala/scalala/tensor/domain/Domain1.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * A domain that explicitly has only one element, i.e. A is not a tuple. * * @author dramage */ trait Domain1Like[@specialized(Int,Long) A, +This<:Domain1[A]] extends IterableDomainLike[A,This] { outer => override def repr: This = this.asInstanceOf[This]; /** Constructs the union of this and the other domain. */ override def union(that : IterableDomain[A]) : IterableDomain[A] = that match { case d1 : Domain1[_] => this.union(d1.asInstanceOf[Domain1[A]]); case _ => super.union(that); } /** Constructs the union of this and the other domain. */ def union(that : Domain1[A]) : Domain1[A] = { new Domain1[A] with UnionDomainLike[A,Domain1[A]] { override def a = outer.repr; override def b = that; } } def product[B,That<:Domain1[B]](that : That) = Domain2(repr,that); } /** * A domain that explicitly has only one element, i.e. A is not a tuple. * * @author dramage */ trait Domain1[@specialized(Int,Long) A] extends IterableDomain[A] with Domain1Like[A,Domain1[A]]; ================================================ FILE: src/main/scala/scalala/tensor/domain/Domain2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * Implementation trait for a domain containing all pairs from * two underlying domains. * * @author dramage */ trait Domain2Like [@specialized(Int,Long) A1, @specialized(Int,Long) A2, +D1 <: Domain1[A1] with Domain1Like[A1,D1], +D2 <: Domain1[A2] with Domain1Like[A2,D2], +Transpose <: Domain2Like[A2,A1,D2,D1,This,Transpose], +This <: Domain2Like[A1,A2,D1,D2,Transpose,This]] extends IterableDomain[(A1,A2)] with DomainLike[(A1,A2),This] { /** Row-space domain. */ def _1 : D1; /** Col-space domain. */ def _2 : D2; /** Constructs the union of this and the other domain. */ override def union(that : IterableDomain[(A1,A2)]) : IterableDomain[(A1,A2)] = that match { case d1 : Domain2[_,_] => { val casted = d1.asInstanceOf[Domain2[A1,A2]]; Domain2(this._1 union casted._1, this._2 union casted._2); } case _ => super.union(that); } /** Returns the transpose of this domain. */ def transpose : Transpose; override def foreach[O](fn : ((A1,A2)) => O) = for (k1 <- _1.iterator; k2 <- _2.iterator) fn((k1,k2)); /** Iterators all elements of this domain. */ override def iterator = for (k1 <- _1.iterator; k2 <- _2.iterator) yield (k1,k2); /** Returns true if a1 is in the row space and a2 is in the col space. */ def contains(a1 : A1, a2 : A2) = _1.contains(a1) && _2.contains(a2); /** Defers to contains(tup._1, tup._2). */ final override def contains(tup : (A1,A2)) = contains(tup._1, tup._2); override def equals(other : Any) = other match { case that : Domain2[_,_] => this._1 == that._1 && this._2 == that._2; case _ => super.equals(other); } } /** * All pairs of elements from D1 and D2, both iterable domains. * * @author dramage */ trait Domain2 [@specialized(Int,Long) A1, @specialized(Int,Long) A2] extends Product2[Domain1[A1],Domain1[A2]] with IterableDomain[(A1,A2)] with Domain2Like[A1,A2,Domain1[A1],Domain1[A2],Domain2[A2,A1],Domain2[A1,A2]] { def transpose = Domain2[A2,A1](_2,_1); override def size = _1.size * _2.size; override def canEqual(that : Any) = that.isInstanceOf[Domain2[_,_]]; override def toString = "Domain2("+_1.toString+","+_2.toString+")"; } object Domain2 { def apply[A1,A2](d1 : Domain1[A1], d2 : Domain1[A2]) : Domain2[A1,A2] = new Impl(d1,d2); class Impl[@specialized(Int,Long) A1, @specialized(Int,Long) A2] (override val _1 : Domain1[A1], override val _2 : Domain1[A2]) extends Domain2[A1,A2]; } ================================================ FILE: src/main/scala/scalala/tensor/domain/DomainN.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * A domain indexed by sequences of underyling key type K. * * @author dramage */ case class DomainN[@specialized(Int) K](components : Seq[IterableDomain[K]]) extends IterableDomain[Seq[K]] with IterableDomainLike[Seq[K],DomainN[K]] { override def size = components.map(_.size).reduceLeft(_ * _); override def union(other : IterableDomain[Seq[K]]) = other match { case that : DomainN[_] => { val casted = that.asInstanceOf[DomainN[K]]; require(this.components.size == casted.components.size, "Can only take the union of product domains of the same size"); DomainN((this.components zip casted.components) map (tup => tup._1 union tup._2)); } case _ => super.union(other); } override def foreach[O](fn : (Seq[K] => O)) = { def unroll(key : List[K], remaining : Seq[IterableDomain[K]]) { require(remaining.length > 0); if (remaining.length == 1) { remaining.head.foreach(e => fn(key :+ e)); } else { remaining.head.foreach(e => unroll(key :+ e, remaining.tail)); } } unroll(List.empty[K], components); } /** Iterators all elements of this domain. */ override def iterator = { def unroll(remaining : Seq[IterableDomain[K]]) : Iterator[Seq[K]] = { require(remaining.length > 0); if (remaining.length == 1) { remaining.head.iterator.map(k => List(k)); } else { for (k <- remaining.head.iterator; rest <- unroll(remaining.tail)) yield List(k) ++ rest; } } unroll(components); } /** Returns true if a1 is in the row space and a2 is in the col space. */ def contains(k : Seq[K]) = (components.length == k.length) && (components zip k).forall(tup => tup._1 contains tup._2); override def equals(other : Any) = other match { case that : DomainN[_] => this.components == that.components case base : Domain[_] => super.equals(base); case _ => false; } } ================================================ FILE: src/main/scala/scalala/tensor/domain/IndexDomain.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * The domain of indices: ints starting from 0 up to a bounded size. * * @author dramage */ case class IndexDomain(override val size : Int) extends Domain1[Int] with Domain1Like[Int,IndexDomain] { override def foreach[O](fn : Int=>O) = { var i = 0; while (i < size) { fn(i); i += 1; } } override def product[B,That<:Domain1[B]](that : That) = that match { case IndexDomain(otherSize) => TableDomain(size,otherSize); case _ => super.product[B,That](that); } override def toIndexedSeq[B>:Int] = Range(0,size); override def contains(key : Int) = key >= 0 && key < size; override def union(other : IterableDomain[Int]) = other match { case that : IndexDomain => IndexDomain(this.size max that.size); case _ => super.union(other); } override def iterator = Iterator.range(0, size); override def toString = "IndexDomain("+size+")"; override def equals(other : Any) = other match { case IndexDomain(s) => this.size == s; case _ => super.equals(other); } } ================================================ FILE: src/main/scala/scalala/tensor/domain/IterableDomain.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * Implementation trait for a domain that can be traversed. Default * equality check returns true if this eq other or if this and other * traverse the same elements in the same order. * * @author dramage */ trait IterableDomainLike[@specialized(Int,Long) A, +This<:IterableDomain[A]] extends DomainLike[A,This] with Iterable[A] { outer => override def repr: This = this.asInstanceOf[This]; /** Applies the given function to every element of the domain. */ def foreach[O](f : A => O); /** Iterates over the elements of the domain. */ def iterator : Iterator[A]; /** Constructs the union of this and the other domain. */ def union(that : IterableDomain[A]) : IterableDomain[A] = { new IterableDomain[A] with UnionDomainLike[A,IterableDomain[A]] { override def a = outer.repr; override def b = that; } } /** Number of elements in the domain. */ def size : Int; // def toIndexedSeq = // iterator.toIndexedSeq; // def toArray(implicit mf : Manifest[A]) = // iterator.toArray; // def filter(fn : A => Boolean) : List[A] = // iterator.filter(fn).toList; // def max(implicit ord : Ordering[A]) = // iterator.max(ord); // def min(implicit ord : Ordering[A]) = // iterator.min(ord); override def equals(other : Any) = other match { case that : IterableDomain[_] => (this eq that) || (this.iterator zip that.iterator).forall(tup => tup._1 == tup._2); case _ => false; } } /** * A domain that can be traversed. * * @author dramage */ trait IterableDomain[@specialized(Int,Long) A] extends Domain[A] with IterableDomainLike[A,IterableDomain[A]]; ================================================ FILE: src/main/scala/scalala/tensor/domain/SetDomain.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * The domain of elements from a specific set. * * @author dramage */ case class SetDomain[@specialized(Int,Long) A](set : scala.collection.Set[A]) extends Domain1[A] with Domain1Like[A,SetDomain[A]] { override def size = set.size; override def foreach[O](fn : A=>O) = set.foreach(fn); override def iterator = set.iterator; override def contains(key : A) : Boolean = set.contains(key); override def equals(other : Any) = other match { case SetDomain(s) => this.set == s; case that : Domain[_] => super.equals(that); case _ => false; } } ================================================ FILE: src/main/scala/scalala/tensor/domain/TableDomain.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * An immutable Domain2 indexed by rows and columns. * * @author dramage */ case class TableDomain(numRows : Int, numCols : Int) extends Product2[IndexDomain,IndexDomain] with Domain2[Int,Int] with Domain2Like[Int,Int,IndexDomain,IndexDomain,TableDomain,TableDomain] { override val _1 : IndexDomain = IndexDomain(numRows); override val _2 : IndexDomain = IndexDomain(numCols); override def transpose = TableDomain(numCols, numRows); override def foreach[O](fn : (((Int,Int))=>O)) = { var i = 0; while (i < numRows) { var j = 0; while (j < numCols) { fn((i,j)); j += 1; } i += 1; } } override def union(other : IterableDomain[(Int,Int)]) : IterableDomain[(Int,Int)] = other match { case that : TableDomain => TableDomain(this.numRows max that.numRows, this.numCols max that.numCols); case _ => super.union(other); } override def toString = "TableDomain("+numRows+","+numCols+")"; override def equals(other : Any) = other match { case TableDomain(nr,nc) => this.numRows == nr && this.numCols == nc; case _ => super.equals(other); } } ================================================ FILE: src/main/scala/scalala/tensor/domain/UnionDomain.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package domain; /** * Trait that represents the union of two domains. * * @author dramage */ trait UnionDomainLike[@specialized(Int,Long) A, +This<:IterableDomain[A]] extends IterableDomainLike[A, This] { def a : IterableDomain[A]; def b : IterableDomain[A]; override def size = { var s = 0; foreach(k => { s += 1; }) s } override def foreach[O](fn : A=>O) = { a.foreach(fn); b.foreach(k => if (!a.contains(k)) fn(k)); } override def iterator = a.iterator ++ b.iterator.filterNot(a.contains); override def contains(key : A) : Boolean = a.contains(key) || b.contains(key); override def equals(other : Any) = other match { case that : UnionDomainLike[_,_] => this.a == that.a && this.b == that.b; case _ => super.equals(other); } } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorBuilder.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; /** * Builds a Tensor of type To after being given a series of * key, value pairs. * * @author dramage */ trait TensorBuilder[@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V,+To] { def update(key : K, value : V); def result : To; } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorKeysMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._; /** * Support for comprehensions on keys from an underlying tensor. This * class can be implicitly viewed as an Iterable[K]. * * @author dramage */ trait TensorKeysMonadic [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] { def repr : This; /** Calls repr.foreachKey. */ def foreach[U](fn : K => U) = repr.foreachKey(fn); /** Calls repr.size. */ def size = repr.size; /** Calls repr.keysIterator. */ def iterator = repr.keysIterator; /** Constructs a filtered view of this tensor. */ def filter[D,That](p : K => Boolean) = withFilter(p); /** Constructs a filtered view of this tensor. */ def withFilter(p : K => Boolean) = new TensorKeysMonadic.Filtered[K,V,This](repr, p); } object TensorKeysMonadic { /** Filtered view of the keys in a Tensor. Does not support map. */ class Filtered [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] (val repr : This, p : K=>Boolean) { def foreach[U](fn : K => U) = repr.foreachKey(k => if (p(k)) fn(k)); def withFilter(q : K => Boolean) = new Filtered[K,V,This](repr, k => p(k) && q(k)); // def map[U,D,That](fn : K => U) // (implicit df : CanGetDomain[This,D], bf : CanBuildTensorFrom[This,D,K,U,That]) = { // val builder = bf(repr, repr.domain.asInstanceOf[D]); // repr.foreachPair((k,v) => if (p(k)) builder(k) = fn(k)); // builder.result; // } // // def strict[D,That] // (implicit df : CanGetDomain[This,D], bf : CanBuildTensorFrom[This,D,K,V,That]) = { // val builder = bf(repr, repr.domain.asInstanceOf[D]); // repr.foreachPair((k,v) => if (p(k)) builder(k) = v); // builder.result; // } } implicit def asIterable[K, V, T<:Tensor[K,V]](values : TensorKeysMonadic[K,V,T]) = { new Iterable[K] { def self = values.repr; override def foreach[U](fn : K => U) = self.foreachKey(fn); override def iterator = self.keysIterator; } } } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorNonZeroKeysMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._; /** * Support for comprehensions on all non-zero-valued keys (and some zeros) from * an underlying tensor. This class can be implicitly viewed as an Iterable[K]. * * @author dramage */ trait TensorNonZeroKeysMonadic [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] { def repr : This; /** Calls repr.foreachKey. */ def foreach[U](fn : K => U) = repr.foreachNonZeroKey(fn); /** Calls repr.nonzeroSize. */ def size = repr.nonzeroSize; /** Calls repr.keysIterator. */ def iterator = repr.keysIteratorNonZero; /** Constructs a filtered view of this tensor. */ def filter[D,That](p : K => Boolean) = withFilter(p); /** Constructs a filtered view of this tensor. */ def withFilter(p : K => Boolean) = new TensorNonZeroKeysMonadic.Filtered[K,V,This](repr, p); } object TensorNonZeroKeysMonadic { /** Filtered view of the keys in a Tensor. Does not support map. */ class Filtered [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] (val repr : This, p : K=>Boolean) { def foreach[U](fn : K => U) = repr.foreachNonZeroKey(k => if (p(k)) fn(k)); def withFilter(q : K => Boolean) = new Filtered[K,V,This](repr, k => p(k) && q(k)); } implicit def asIterable[K, V, T<:Tensor[K,V]](values : TensorNonZeroKeysMonadic[K,V,T]) = { new Iterable[K] { def self = values.repr; override def foreach[U](fn : K => U) = self.foreachNonZeroKey(fn); override def iterator = self.keysIteratorNonZero; } } } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorNonZeroMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._ import operators.HasValuesMonadic ; /** * For comprehensions on pairs of values from an underlying tensor. This * class can be implicitly viewed as a Map[K,V]. * * @author dramage */ trait TensorNonZeroMonadic [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] extends HasValuesMonadic[This,V] { self => /** Underlying tensor. */ def repr : This; /** Calls repr.nonzeroSize. */ def size = repr.nonzeroSize; /** Gets a Monadic for the nonzero pairs. */ def pairs : TensorNonZeroPairsMonadic[K,V,This] = new TensorNonZeroPairsMonadic[K,V,This] { override def repr = self.repr }; /** Gets a Monadic for the nonzero keys. */ def keys : TensorNonZeroKeysMonadic[K,V,This] = new TensorNonZeroKeysMonadic[K,V,This] { override def repr = self.repr }; /** Gets a Monadic for the nonzero values. */ def values : TensorNonZeroValuesMonadic[K,V,This] = new TensorNonZeroValuesMonadic[K,V,This] { override def repr = self.repr }; } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorNonZeroPairsMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._; /** * For comprehensions on pairs of values from an underlying tensor. This * class can be implicitly viewed as a Map[K,V]. * * @author dramage */ trait TensorNonZeroPairsMonadic [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] { self => /** Underlying tensor. */ def repr : This; /** Calls repr.foreachPair. */ def foreach[U](fn : ((K,V)) => U) = repr.foreachNonZeroPair((k,v) => fn((k,v))); /** Calls repr.nonzeroSize. */ def size = repr.nonzeroSize; /** Calls repr.mapPairs. */ def map[TT>:This,O,That](fn : ((K,V)) => O) (implicit bf : CanMapKeyValuePairs[TT, K, V, O, That]) : That = repr.mapNonZeroPairs((k,v) => fn((k,v)))(bf.asInstanceOf[CanMapKeyValuePairs[Tensor[K,V],K,V,O,That]]); /** Calls repr.pairsIterator. */ def iterator = repr.pairsIteratorNonZero; /** Constructs a filtered view of this tensor. */ def filter(p : ((K,V)) => Boolean) = withFilter(p); /** Constructs a filtered view of this tensor. */ def withFilter(p : ((K,V)) => Boolean) = new TensorNonZeroPairsMonadic.Filtered[K,V,This](repr, p); } object TensorNonZeroPairsMonadic { /** Filtered view of the pairs in a Tensor. Does not support map. */ class Filtered [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] (val repr : This, p : ((K,V))=>Boolean) { def foreach[U](fn : ((K,V)) => U) = repr.foreachNonZeroPair((k,v) => if (p((k,v))) fn((k,v))); def withFilter(q : ((K,V)) => Boolean) = new Filtered[K,V,This](repr, tup => p(tup) && q(tup)); } implicit def asMap[K,V,T<:Tensor[K,V]](pairs : TensorNonZeroPairsMonadic[K,V,T]) = { new scala.collection.Map[K,V] { def self = pairs.repr; override def foreach[U](fn : ((K,V)) => U) = pairs.foreach(fn); override def keysIterator = self.keysIteratorNonZero; override def valuesIterator = self.valuesIteratorNonZero; override def contains(key : K) = self.isDefinedAt(key); override def apply(key : K) = self.apply(key); override def iterator = self.pairsIteratorNonZero; override def get(key : K) = if (self.isDefinedAt(key)) Some(self.apply(key)) else None; override def - (key : K) = this.toMap.-(key); override def + [V1>:V](kv : (K,V1)): scala.collection.Map[K,V1] = this.toMap.+(kv); } } } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorNonZeroTriplesMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._ import scala.collection.generic.CanBuildFrom import operators.HasValuesMonadic /** * For comprehensions on nonzero triples of values from an underlying 2-axis tensor. * This class can be implicitly viewed as an Iterable[(K1,K2,V)]. * * @author dramage */ trait TensorNonZeroTriplesMonadic [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +This<:Tensor2[K1,K2,V]] { /** Underlying tensor. */ def repr : This; /** Calls repr.foreachTriple. */ def foreach[U](fn : ((K1,K2,V)) => U) = repr.foreachNonZeroTriple((k1,k2,v) => fn((k1,k2,v))); /** Calls repr.size. */ def size = repr.size; /** Calls repr.mapTriples. */ def map[TT>:This,O,That](fn : ((K1,K2,V)) => O) (implicit bf : CanMapKeyValuePairs[TT, (K1,K2), V, O, That]) : That = repr.mapNonZeroTriples((k1,k2,v) => fn((k1,k2,v)))(bf.asInstanceOf[CanMapKeyValuePairs[Tensor2[K1,K2,V],(K1,K2),V,O,That]]); /** Calls repr.TriplesIterator. */ def iterator = repr.triplesIteratorNonZero; /** Constructs a filtered view of this tensor. */ def filter(p : ((K1,K2,V)) => Boolean) = withFilter(p); /** Constructs a filtered view of this tensor. */ def withFilter(p : ((K1,K2,V)) => Boolean) = new TensorNonZeroTriplesMonadic.Filtered[K1,K2,V,This](repr, p); } object TensorNonZeroTriplesMonadic { /** Filtered view of the Triples in a Tensor. Does not support map. */ class Filtered [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +This<:Tensor2[K1,K2,V]] (val repr : This, p : ((K1,K2,V))=>Boolean) { def foreach[U](fn : ((K1,K2,V)) => U) = repr.foreachNonZeroTriple((k1,k2,v) => if (p((k1,k2,v))) fn((k1,k2,v))); def withFilter(q : ((K1,K2,V)) => Boolean) = new Filtered[K1,K2,V,This](repr, tup => p(tup) && q(tup)); /** Calls repr.mapTriples. */ def map[O,That](fn : ((K1,K2,V)) => O) (implicit bf : CanBuildFrom[Iterable[(K1,K2,V)],O,That]) : That = { val b = bf(); repr.foreachNonZeroTriple((k1,k2,v) => if(p((k1,k2,v))) b += fn((k1,k2,v))); b.result; } } implicit def asIterable[K1, K2, V, T<:Tensor2[K1,K2,V]](values : TensorTriplesMonadic[K1,K2,V,T]) = { new Iterable[(K1,K2,V)] { def self = values.repr; override def foreach[U](fn : ((K1,K2,V)) => U) = self.foreachNonZeroTriple((i,j,v) => fn((i,j,v))); override def iterator = self.triplesIteratorNonZero; } } } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorNonZeroValuesMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._ import operators.ValuesMonadic /** * Support for comprehensions on values from an underlying tensor. This * class can be implicitly viewed as an Iterable[V]. * * @author dramage */ trait TensorNonZeroValuesMonadic [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] extends ValuesMonadic[This,V] { /** Underlying tensor. */ def repr : This; /** Calls repr.foreachValue. */ def foreach[U](fn : V => U) = repr.foreachNonZeroValue(fn); /** Calls repr.nonzeroSize. */ def size = repr.nonzeroSize; /** Calls repr.mapValues. */ override def map[TT>:This,O,That](fn : V => O) (implicit bf : CanMapValues[TT, V, O, That]) : That = repr.mapNonZeroValues(fn)(bf.asInstanceOf[CanMapValues[Tensor[K,V],V,O,That]]); /** Calls repr.valuesIterator. */ def iterator = repr.valuesIteratorNonZero; /** Constructs a filtered view of this tensor. */ def filter[D,That](p : V => Boolean) = withFilter(p); /** Constructs a filtered view of this tensor. */ def withFilter(p : V => Boolean) = new TensorNonZeroValuesMonadic.Filtered[K,V,This](repr, p); } object TensorNonZeroValuesMonadic { /** Filtered view of the values in a Tensor. Does not support map. */ class Filtered [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] (val repr : This, p : V=>Boolean) { def foreach[U](fn : V => U) = repr.foreachNonZeroValue(v => if (p(v)) fn(v)); def withFilter(q : V => Boolean) = new Filtered[K,V,This](repr, v => p(v) && q(v)); // def map[U,D,That](fn : V => U) // (implicit df : CanGetDomain[This,D], bf : CanBuildTensorFrom[This,D,K,U,That]) = { // val builder = bf(repr, repr.domain.asInstanceOf[D]); // repr.foreachPair((k,v) => if (p(v)) builder(k) = fn(v)); // builder.result; // } // // def strict[D,That] // (implicit df : CanGetDomain[This,D], bf : CanBuildTensorFrom[This,D,K,V,That]) = { // val builder = bf(repr, repr.domain.asInstanceOf[D]); // repr.foreachPair((k,v) => if (p(v)) builder(k) = v); // builder.result; // } } implicit def asIterable[K, @specialized(Int,Long,Float,Double) V, T<:Tensor[K,V]] (values : TensorNonZeroValuesMonadic[K,V,T]) = { new Iterable[V] { def self = values.repr; override def foreach[U](fn : V => U) = self.foreachNonZeroValue(fn); override def iterator = self.valuesIteratorNonZero; } } } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorPairsMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._ import scala.collection.generic.CanBuildFrom import operators.HasValuesMonadic /** * For comprehensions on pairs of values from an underlying tensor. This * class can be implicitly viewed as a Map[K,V]. * * @author dramage */ trait TensorPairsMonadic [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] { /** Underlying tensor. */ def repr : This; /** Calls repr.foreachPair. */ def foreach[U](fn : ((K,V)) => U) = repr.foreachPair((k,v) => fn((k,v))); /** Calls repr.size. */ def size = repr.size; /** Calls repr.mapPairs. */ def map[TT>:This,O,That](fn : ((K,V)) => O) (implicit bf : CanMapKeyValuePairs[TT, K, V, O, That]) : That = repr.mapPairs((k,v) => fn((k,v)))(bf.asInstanceOf[CanMapKeyValuePairs[Tensor[K,V],K,V,O,That]]); /** Calls repr.pairsIterator. */ def iterator = repr.pairsIterator; /** Constructs a filtered view of this tensor. */ def filter(p : ((K,V)) => Boolean) = withFilter(p); /** Constructs a filtered view of this tensor. */ def withFilter(p : ((K,V)) => Boolean) = new TensorPairsMonadic.Filtered[K,V,This](repr, p); } object TensorPairsMonadic { /** Filtered view of the pairs in a Tensor. Does not support map. */ class Filtered [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] (val repr : This, p : ((K,V))=>Boolean) { def foreach[U](fn : ((K,V)) => U) = repr.foreachPair((k,v) => if (p((k,v))) fn((k,v))); def withFilter(q : ((K,V)) => Boolean) = new Filtered[K,V,This](repr, tup => p(tup) && q(tup)); /** Calls repr.mapPairs. */ def map[O,That](fn : ((K,V)) => O) (implicit bf : CanBuildFrom[Iterable[(K,V)],O,That]) : That = { val b = bf(); repr.foreachPair( (k,v) => if(p(k -> v)) b += fn(k->v) ) b.result; } } implicit def asMap[K,V,T<:Tensor[K,V]](pairs : TensorPairsMonadic[K,V,T]) = { new scala.collection.Map[K,V] { def self = pairs.repr; override def foreach[U](fn : ((K,V)) => U) = pairs.foreach(fn); override def keysIterator = self.keysIterator; override def valuesIterator = self.valuesIterator; override def contains(key : K) = self.isDefinedAt(key); override def apply(key : K) = self.apply(key); override def iterator = self.pairsIterator; override def get(key : K) = if (self.isDefinedAt(key)) Some(self.apply(key)) else None; override def - (key : K) = this.toMap.-(key); override def + [V1>:V](kv : (K,V1)): scala.collection.Map[K,V1] = this.toMap.+(kv); } } } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorTriplesMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._ import scala.collection.generic.CanBuildFrom import operators.HasValuesMonadic /** * For comprehensions on Triples of values from an underlying 2-axis tensor. * This class can be implicitly viewed as an Iterable[(K1,K2,V)]. * * @author dramage */ trait TensorTriplesMonadic [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +This<:Tensor2[K1,K2,V]] { /** Underlying tensor. */ def repr : This; /** Calls repr.foreachTriple. */ def foreach[U](fn : ((K1,K2,V)) => U) = repr.foreachTriple((k1,k2,v) => fn((k1,k2,v))); /** Calls repr.size. */ def size = repr.size; /** Calls repr.mapTriples. */ def map[TT>:This,O,That](fn : ((K1,K2,V)) => O) (implicit bf : CanMapKeyValuePairs[TT, (K1,K2), V, O, That]) : That = repr.mapTriples((k1,k2,v) => fn((k1,k2,v)))(bf.asInstanceOf[CanMapKeyValuePairs[Tensor2[K1,K2,V],(K1,K2),V,O,That]]); /** Calls repr.TriplesIterator. */ def iterator = repr.triplesIterator; /** Constructs a filtered view of this tensor. */ def filter(p : ((K1,K2,V)) => Boolean) = withFilter(p); /** Constructs a filtered view of this tensor. */ def withFilter(p : ((K1,K2,V)) => Boolean) = new TensorTriplesMonadic.Filtered[K1,K2,V,This](repr, p); } object TensorTriplesMonadic { /** Filtered view of the Triples in a Tensor. Does not support map. */ class Filtered [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +This<:Tensor2[K1,K2,V]] (val repr : This, p : ((K1,K2,V))=>Boolean) { def foreach[U](fn : ((K1,K2,V)) => U) = repr.foreachTriple((k1,k2,v) => if (p((k1,k2,v))) fn((k1,k2,v))); def withFilter(q : ((K1,K2,V)) => Boolean) = new Filtered[K1,K2,V,This](repr, tup => p(tup) && q(tup)); /** Calls repr.mapTriples. */ def map[O,That](fn : ((K1,K2,V)) => O) (implicit bf : CanBuildFrom[Iterable[(K1,K2,V)],O,That]) : That = { val b = bf(); repr.foreachTriple((k1,k2,v) => if(p((k1,k2,v))) b += fn((k1,k2,v))); b.result; } } implicit def asIterable[K1, K2, V, T<:Tensor2[K1,K2,V]](values : TensorTriplesMonadic[K1,K2,V,T]) = { new Iterable[(K1,K2,V)] { def self = values.repr; override def foreach[U](fn : ((K1,K2,V)) => U) = self.foreachTriple((i,j,v) => fn((i,j,v))); override def iterator = self.triplesIterator; } } } ================================================ FILE: src/main/scala/scalala/tensor/generic/TensorValuesMonadic.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package generic; import domain.CanGetDomain; import scalala.generic.collection._ import operators.ValuesMonadic; /** * Support for comprehensions on values from an underlying tensor. This * class can be implicitly viewed as an Iterable[V]. * * @author dramage */ trait TensorValuesMonadic [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] extends ValuesMonadic[This,V] { /** Underlying tensor. */ def repr : This; /** Calls repr.foreachValue. */ def foreach[U](fn : V => U) = repr.foreachValue(fn); /** Calls repr.size. */ def size = repr.size; /** Calls repr.mapValues. */ override def map[TT>:This,O,That](fn : V => O) (implicit bf : CanMapValues[TT, V, O, That]) : That = repr.mapValues(fn)(bf.asInstanceOf[CanMapValues[Tensor[K,V],V,O,That]]); /** Calls repr.valuesIterator. */ def iterator = repr.valuesIterator; /** Constructs a filtered view of this tensor. */ def filter[D,That](p : V => Boolean) = withFilter(p); /** Constructs a filtered view of this tensor. */ def withFilter(p : V => Boolean) = new TensorValuesMonadic.Filtered[K,V,This](repr, p); } object TensorValuesMonadic { /** Filtered view of the values in a Tensor. Does not support map. */ class Filtered [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +This<:Tensor[K,V]] (val repr : This, p : V=>Boolean) { def foreach[U](fn : V => U) = repr.foreachValue(v => if (p(v)) fn(v)); def withFilter(q : V => Boolean) = new Filtered[K,V,This](repr, v => p(v) && q(v)); // def map[U,D,That](fn : V => U) // (implicit df : CanGetDomain[This,D], bf : CanBuildTensorFrom[This,D,K,U,That]) = { // val builder = bf(repr, repr.domain.asInstanceOf[D]); // repr.foreachPair((k,v) => if (p(v)) builder(k) = fn(v)); // builder.result; // } // // def strict[D,That] // (implicit df : CanGetDomain[This,D], bf : CanBuildTensorFrom[This,D,K,V,That]) = { // val builder = bf(repr, repr.domain.asInstanceOf[D]); // repr.foreachPair((k,v) => if (p(v)) builder(k) = v); // builder.result; // } } implicit def asIterable[K, @specialized(Int,Long,Float,Double) V, T<:Tensor[K,V]] (values : TensorValuesMonadic[K,V,T]) = { new Iterable[V] { def self = values.repr; override def foreach[U](fn : V => U) = self.foreachValue(fn); override def iterator = self.valuesIterator; } } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/CRSTensor2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain._; import scalala.scalar.Scalar; import scalala.generic.collection._ import tensor.Counter2.Curried import scala.collection.mutable.HashMap ; /** * A mutable Tensor2 with an open row key domain that maps to an arbitrary Tensor1 as its rows. * * CRS = Compress Row Storage * * @author dlwh */ trait CRSTensor2Like [K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +M1[VV]<:Curried[scala.collection.mutable.Map,K1]#Result[VV], +T<:scalala.tensor.mutable.Tensor1[K2,V], +This<:CRSTensor2[K1,K2,V,T]] extends tensor.CRSTensor2Like[K1,K2,V,M1,T,This] with Tensor2Like[K1,K2,V,SetDomain[K1], SetDomain[K2], Domain2[K1,K2], Domain2[K2,K1], This] { self => def update(k1 : K1, k2: K2, v : V) = innerGetOrElseUpdate(k1,data)(k2) = v; private[mutable] def innerGetOrElseUpdate[M](k:K1, m: scala.collection.mutable.Map[K1,M]): M = { m.getOrElseUpdate(k,m.default(k)) } } trait CRSTensor2 [K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +T<:Tensor1[K2,V]] extends tensor.CRSTensor2[K1,K2,V,T] with Tensor2[K1,K2,V] with CRSTensor2Like[K1,K2, V,Curried[scala.collection.mutable.Map,K1]#Result,T,CRSTensor2[K1,K2,V,T]]; object CRSTensor2 { class Impl[K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, T<:Tensor1[K2,V]] (override val data : scala.collection.mutable.Map[K1,T], override val k2domain: Domain1[K2]) (implicit override val scalar : Scalar[V], zeros: CanCreateZerosLike[T,T]) extends CRSTensor2[K1,K2,V,T]; /** * Returns a new empty CRSTensor2 using the "template" to create rows. The actual rows are zero'd out versions of * the template. */ def apply[K1,K2,V,T<:Tensor1[K2,V]](template: T)(implicit view: CanViewAsTensor1[T,K2,V], zeros: CanCreateZerosLike[T,T], scalar: Scalar[V]) : mutable.CRSTensor2[K1,K2,V,T] = { val map = new HashMap[K1,T] { override def default(k: K1) = zeros(template); } new Impl[K1,K2,V,T](map, template.domain); } implicit def canSliceRow[K1,K2,V,T<:Tensor1[K2,V]] : CanSliceRow[CRSTensor2[K1,K2,V,T],K1,T] = new CanSliceRow[CRSTensor2[K1,K2,V,T],K1,T] { override def apply(from : CRSTensor2[K1,K2,V,T], row : K1) = from.innerGetOrElseUpdate(row,from.data); } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Counter.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain._; import scalala.scalar.Scalar; import scalala.generic.collection._; /** * A mutable tensor that acts like a collection of key-value pairs backed by * a map. * * @author dramage */ trait CounterLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +M<:scala.collection.mutable.Map[K,V], +This<:Counter[K,V]] extends tensor.CounterLike[K,V,M,This] with Tensor1Like[K,V,SetDomain[K],This] { self => def update(k : K, v : V) = data(k) = v; } trait Counter [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] extends tensor.Counter[K,V] with Tensor1[K,V] with CounterLike[K,V,scala.collection.mutable.Map[K,V],Counter[K,V]]; object Counter { class Impl[@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] (override val data : scala.collection.mutable.Map[K,V]) (implicit override final val scalar : Scalar[V]) extends Counter[K,V] with Serializable; /** Returns an empty counter. */ def apply[K,V:Scalar]() : Counter[K,V] = new Impl(scala.collection.mutable.HashMap[K,V]()); /** Returns a counter by summing all the given values. */ def apply[K,V:Scalar](values : (K,V)*) : Counter[K,V] = apply(values); /** Returns a counter by summing all the given values. */ def apply[K,V:Scalar](values : TraversableOnce[(K,V)]) : Counter[K,V] = { val rv = apply[K,V](); values.foreach({ case (k,v) => rv(k) = rv.scalar.+(v,rv(k)); }); rv; } /** Counts each of the given items. */ def count[K](items : TraversableOnce[K]) : Counter[K,Int] = { val rv = apply[K,Int](); items.foreach(rv(_) += 1); rv; } def count[K](items: K*): mutable.Counter[K,Int] = count(items); def apply[K,V:Scalar](domain : Domain1[K]) : Counter[K,V] = new Impl(scala.collection.mutable.HashMap[K,V]()); // implicit def opCanCopy[K,V:CanCopy] = CanCopy.opMapValues[Counter[K,V],V]; // implicit def opZeros[K,V:Scalar] = CanCreateZerosLike.opMapValues[Counter[K,V],V,Counter[K,V]]; implicit def CanMapValuesCounter [@specialized(Int) K, @specialized(Int,Double) V, @specialized(Int,Double) RV:Scalar]: CanMapValues[Counter[K, V], V, RV, Counter[K, RV]] = new CanMapValues[Counter[K,V],V,RV,Counter[K,RV]] { override def map(from : Counter[K,V], fn : (V=>RV)) = { val rv = Counter[K,RV](); for( (k,v) <- from.pairsIterator) { rv(k) = fn(from.data(k)); } rv; } override def mapNonZero(from : Counter[K,V], fn : (V=>RV)) = { val rv = Counter[K,RV](); for( (k,v) <- from.pairsIteratorNonZero) { rv(k) = fn(from.data(k)); } rv; } } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Counter2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain._; import scalala.scalar.Scalar; import scalala.generic.collection._ import tensor.Counter2.Curried import scala.collection.mutable.HashMap ; /** * A mutable tensor that acts like a collection of key1-key2-value pairs backed by * a map of maps. * * @author dlwh,dramage */ trait Counter2Like [K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V, +M1[VV]<:Curried[scala.collection.mutable.Map,K1]#Result[VV], +T<:scalala.tensor.mutable.Counter[K2,V], +This<:Counter2[K1,K2,V]] extends tensor.Counter2Like[K1,K2,V,M1,T,This] with Tensor2Like[K1,K2,V,SetDomain[K1], SetDomain[K2], Domain2[K1,K2], Domain2[K2,K1], This] { self => def update(k1 : K1, k2: K2, v : V) = innerGetOrElseUpdate(k1,data)(k2) = v; private[mutable] def innerGetOrElseUpdate[M](k:K1, m: scala.collection.mutable.Map[K1,M]): M = { m.getOrElseUpdate(k,m.default(k)) } } trait Counter2 [K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V] extends tensor.Counter2[K1,K2,V] with Tensor2[K1,K2,V] with Counter2Like[K1,K2, V,Curried[scala.collection.mutable.Map,K1]#Result,Counter[K2,V],Counter2[K1,K2,V]]; object Counter2 { class Impl[K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double) V] (override val data : scala.collection.mutable.Map[K1,Counter[K2,V]]) (implicit override val scalar : Scalar[V]) extends Counter2[K1,K2,V] with Serializable; /** Returns a new empty counter. */ def apply[K1,K2,V:Scalar]() : Counter2[K1,K2,V] = { val map = new HashMap[K1,Counter[K2,V]] { override def default(k: K1) = Counter[K2,V](); } new Impl[K1,K2,V](map); } /** Aggregates the counts in the given items. */ def apply[K1,K2,V:Scalar](values : (K1,K2,V)*) : Counter2[K1,K2,V] = apply(values); /** Aggregates the counts in the given items. */ def apply[K1,K2,V:Scalar](values : TraversableOnce[(K1,K2,V)]) : Counter2[K1,K2,V] = { val rv = apply[K1,K2,V](); values.foreach({ case (k1,k2,v) => rv(k1,k2) = rv.scalar.+(rv(k1,k2), v) }); rv; } /** Constructs a Counter2 -- currently ignores the domain. */ def apply[K1,K2,V:Scalar](domain : Domain2[K1,K2]) : Counter2[K1,K2,V] = apply[K1,K2,V](); /** Counts the given elements. */ def count[K1,K2](values : TraversableOnce[(K1,K2)]) : Counter2[K1,K2,Int] = { val rv = apply[K1,K2,Int](); values.foreach({ case (k1,k2) => rv(k1,k2) += 1; }); rv; } implicit def canSliceRow[K1,K2,V](implicit vS : Scalar[V]) : CanSliceRow[Counter2[K1,K2,V],K1,Counter[K2,V]] = new CanSliceRow[Counter2[K1,K2,V],K1,Counter[K2,V]] { override def apply(from : Counter2[K1,K2,V], row : K1) = from.innerGetOrElseUpdate(row,from.data); } implicit def canSliceCol[K1,K2,V](implicit vS : Scalar[V]) : CanSliceCol[Counter2[K1,K2,V],K2,Counter[K1,V]] = new CanSliceCol[Counter2[K1,K2,V],K2,Counter[K1,V]] { override def apply(from : Counter2[K1,K2,V], col : K2) = new Counter[K1,V] { override val data = new scala.collection.mutable.Map[K1,V] { override def apply(k1 : K1) = from(k1,col); override def update(k1 : K1, v : V) = from(k1,col) = v; override def -=(k1 : K1) = { from.data(k1)(col) = vS.zero; this; } override def +=(tup : (K1,V)) = { from.data(tup._1)(col) = (tup._2); this; } override def iterator = for ((k1,map) <- from.data.iterator) yield (k1,map(col)); override def get(k1 : K1) = from.data.get(k1).map(_(col)); override def keySet = from.data.keySet; override def size = from.data.size; } implicit val scalar = vS; } } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Matrix.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{IndexDomain,TableDomain}; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for a MutableTensor that is also a tensor.Matrix. * * @author dramage */ trait MatrixLike [@specialized(Int,Long,Float,Double,Boolean) V, +This<:Matrix[V]] extends tensor.MatrixLike[V,This] with Tensor2Like[Int,Int,V,IndexDomain,IndexDomain,TableDomain,TableDomain,This] { override def t : Matrix[V] = new MatrixTranspose.Impl[V,This](repr); } /** * MutableTensor that is also a tensor.Matrix. * * @author dramage */ trait Matrix [@specialized(Int,Long,Float,Double,Boolean) B] extends tensor.Matrix[B] with Tensor2[Int,Int,B] with MatrixLike[B,Matrix[B]]; object Matrix extends dense.DenseMatrixConstructors { implicit def canSliceRow[V:Scalar] : CanSliceRow[Matrix[V],Int,VectorRow[V]] = new CanSliceRow[Matrix[V],Int,VectorRow[V]] { override def apply(from : Matrix[V], row : Int) = new RowSliceImpl[V,Matrix[V]](from,row); } implicit def canSliceCol[V:Scalar] : CanSliceCol[Matrix[V],Int,VectorCol[V]] = new CanSliceCol[Matrix[V],Int,VectorCol[V]] { override def apply(from : Matrix[V], col : Int) = new ColSliceImpl[V,Matrix[V]](from, col); } implicit def canSliceMatrix[V:Scalar] : CanSliceMatrix[Matrix[V],Int,Int,Matrix[V]] = new CanSliceMatrix[Matrix[V],Int,Int,Matrix[V]] { override def apply(from : Matrix[V], keys1 : Seq[Int], keys2 : Seq[Int]) = new MatrixSliceImpl[V,Matrix[V]](from, keys1, keys2); } trait RowSliceLike[V,+Coll<:Matrix[V],+This<:RowSlice[V,Coll]] extends tensor.Matrix.RowSliceLike[V,Coll,This] with VectorSliceLike[(Int,Int),TableDomain,V,Coll,This] with VectorRowLike[V,This]; trait RowSlice[V,+Coll<:Matrix[V]] extends tensor.Matrix.RowSlice[V,Coll] with VectorSlice[(Int,Int),V,Coll] with VectorRow[V] with RowSliceLike[V,Coll,RowSlice[V,Coll]]; class RowSliceImpl[V,+Coll<:Matrix[V]] (override val underlying : Coll, override val row : Int) (implicit override val scalar : Scalar[V]) extends tensor.Matrix.RowSliceImpl[V,Coll](underlying,row) with RowSlice[V,Coll]; trait ColSliceLike[V,+Coll<:Matrix[V],+This<:ColSlice[V,Coll]] extends tensor.Matrix.ColSliceLike[V,Coll,This] with VectorSliceLike[(Int,Int),TableDomain,V,Coll,This] with VectorColLike[V,This]; trait ColSlice[V,+Coll<:Matrix[V]] extends tensor.Matrix.ColSlice[V,Coll] with VectorSlice[(Int,Int),V,Coll] with VectorCol[V] with ColSliceLike[V,Coll,ColSlice[V,Coll]]; class ColSliceImpl[V,+Coll<:Matrix[V]] (override val underlying : Coll, override val col : Int) (implicit override val scalar : Scalar[V]) extends tensor.Matrix.ColSliceImpl[V,Coll](underlying,col) with ColSlice[V,Coll]; trait MatrixSliceLike[@specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Matrix[V], +This<:MatrixSlice[V,Coll]] extends tensor.Matrix.MatrixSliceLike[V,Coll,This] with TensorSliceLike[(Int,Int),TableDomain,(Int,Int),TableDomain,V,Coll,This] with MatrixLike[V,This] { override def update(i : Int, j : Int, value : V) = underlying.update(lookup1(i), lookup2(j), value); } trait MatrixSlice[@specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Matrix[V]] extends tensor.Matrix.MatrixSlice[V,Coll] with TensorSlice[(Int,Int),(Int,Int),V,Coll] with Matrix[V] with MatrixSliceLike[V,Coll,MatrixSlice[V,Coll]]; class MatrixSliceImpl[V, +Coll<:Matrix[V]] (override val underlying : Coll, override val keys1 : Seq[Int], override val keys2 : Seq[Int]) (implicit override val scalar : Scalar[V]) extends tensor.Matrix.MatrixSliceImpl[V,Coll](underlying,keys1,keys2) with MatrixSlice[V, Coll]; } ================================================ FILE: src/main/scala/scalala/tensor/mutable/MatrixTranspose.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{IndexDomain,TableDomain}; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * A Transpose of any Matrix type is a Matrix. * * @author dramage */ trait MatrixTransposeLike [@specialized(Int,Long,Float,Double) V, +Coll <: Matrix[V], +This <: MatrixTranspose[V,Coll]] extends tensor.MatrixTransposeLike[V,Coll,This] with Tensor2TransposeLike[Int,Int,V,IndexDomain,IndexDomain,TableDomain,TableDomain,Coll,This] with MatrixLike[V,This] { override def domain = underlying.domain.transpose.asInstanceOf[TableDomain]; override def t : Coll = underlying; } /** * A Transpose of any Matrix type is a Matrix. * * @author dramage */ trait MatrixTranspose[@specialized(Int,Long,Float,Double) V, +Coll <: Matrix[V]] extends tensor.MatrixTranspose[V,Coll] with Tensor2Transpose[Int,Int,V,Coll] with Matrix[V] with MatrixTransposeLike[V, Coll, MatrixTranspose[V, Coll]]; object MatrixTranspose { class Impl[V, +Coll <: Matrix[V]] (override val underlying : Coll) (implicit override val scalar : Scalar[V]) extends MatrixTranspose[V,Coll]; } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Tensor.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{IterableDomain,SetDomain,Domain1,IndexDomain,Domain2,TableDomain}; import generic.TensorBuilder; import scalala.generic.collection._; import scalala.scalar.Scalar import operators._ /** * Implementation trait for TensorLike. Supports assigning, * updating, and transforming values. * * @author dramage */ trait TensorLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +D<:IterableDomain[K], +Repr<:Tensor[K,V]] extends tensor.TensorLike[K, V, D, Repr] with operators.MutableNumericOps[Repr] { self => /** * Update an individual value. The given key must be in the * map's domain, but need not be in its activeDomain. */ def update(key : K, value : V) : Unit; /** Tranforms all key value pairs in this map by applying the given function. */ def transformPairs(f : (K,V)=>V) = this.foreachPair((k,v) => update(k,f(k,v))); /** * Uses the given function to update all elements of the domain * that have a non-zero values (and possibly some that have zeros, too). * * @return true if all elements in the map were visited. */ def transformNonZeroPairs(fn : ((K,V)=>V)) : Boolean = { this.transformPairs(fn); true; } /** Tranforms all values in this map by applying the given function. */ def transformValues(f : V=>V) = this.foreachPair((k,v) => update(k,f(v))); /** * Uses the given function to update all elements of the domain * that have a non-zero values (and possibly some that have zeros, too). * * @return true if all elements in the map were visited. */ def transformNonZeroValues(fn : (V=>V)) = { this.transformValues(fn); true; } /** * Returns a view of this tensor as a builder for itself. This is used * so that you can construct the appropriate return instance and then * call asBuilder to get a builder view of it. */ def asBuilder : TensorBuilder[K,V,Tensor[K,V]] = new TensorBuilder[K,V,Tensor[K,V]] { def update(k : K, v : V) = self(k) = v; def result = repr; } } /** * Supports assigning, updating, and transforming values. * * @author dramage */ trait Tensor [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V] extends tensor.Tensor[K,V] with TensorLike[K,V,IterableDomain[K],Tensor[K,V]]; object Tensor extends TensorImplicitsLevel1 { /** Constructs a tensor for the given domain. */ def apply[K,V:Scalar](domain : IterableDomain[K]) : Tensor[K,V] = domain match { case d : IndexDomain => VectorCol(d); case d : Domain1[_] => Tensor1(d); case d : TableDomain => Matrix(d); case d : Domain2[_,_] => Tensor2(d); case _ => new Impl[K,V](domain, scala.collection.mutable.Map[K,V]()); } /** Default implementation on a closed domain. */ class Impl[K, V] (override val domain : IterableDomain[K], protected val data : scala.collection.mutable.Map[K,V]) (implicit override val scalar : Scalar[V]) extends Tensor[K, V] { override def size = domain.size; override def apply(key : K) : V = { checkKey(key); data.getOrElse(key, scalar.zero); } override def update(key : K, value : V) = { checkKey(key); data.update(key, value); } } implicit def canSliceTensor[K1, K2, V:Scalar] = new CanSliceTensor[Tensor[K1,V], K1, K2, Tensor[K2,V]] { override def apply(from : Tensor[K1,V], keymap : scala.collection.Map[K2,K1]) = new TensorSlice.FromKeyMap[K1, K2, V, Tensor[K1,V]](from, keymap); } implicit def canSliceVector[K, V:Scalar] = new CanSliceVector[Tensor[K,V], K, VectorCol[V]] { override def apply(from : Tensor[K,V], keys : Seq[K]) = new VectorColSlice.FromKeySeq[K,V,Tensor[K,V]](from, keys); } } /** * Low priority implicits for mutable tensor updates (with cast). * * @author dramage */ trait TensorImplicitsLevel0 { implicit def opSetTensorTensorCast[K,V1,V2,A,B] (implicit v1 : A=>Tensor[K,V1], v2 : B=>tensor.Tensor[K,V2], cast : CanCast[V2,V1], jj : CanJoin[A,B,K,V1,V2]) : BinaryUpdateOp[A,B,OpSet] = new BinaryUpdateOp[A,B,OpSet] { def opType = OpSet; override def apply(a : A, b : B) = { val _a = v1(a); jj.joinAll(a,b,(k,v1,v2) => _a(k) = cast(v2)); } } implicit def opSetTensorScalarCast[K,V1,V2] (implicit cast : CanCast[V2,V1], s1 : Scalar[V1], s2 : Scalar[V2]) : BinaryUpdateOp[Tensor[K,V1],V2,OpSet] = new BinaryUpdateOp[Tensor[K,V1],V2,OpSet] { def opType = OpSet; override def apply(a : Tensor[K,V1], b : V2) = { val newV = cast(b); a.transformPairs((k,oldV) => newV); } } } /** * Higher priority implicits for mutable tensor updates (no cast). * * @author dramage */ trait TensorImplicitsLevel1 extends TensorImplicitsLevel0 { implicit def opUpdateTensorTensor[K,V1,V2,Op<:OpType,A,B] (implicit v1 : A=>Tensor[K,V1], v2 : B=>tensor.Tensor[K,V2], op : BinaryOp[V1,V2,Op,V1], jj : CanJoin[A,B,K,V1,V2]) : BinaryUpdateOp[A,B,Op] = new BinaryUpdateOp[A,B,Op] { override def opType = op.opType; override def apply(a : A, b : B) = { val _a = v1(a); jj.joinEitherNonZero(a,b,(k,v1,v2) => _a(k) = op(v1,v2)); } } implicit def opSetTensorTensor[K,V,A,B] (implicit v1 : A=>Tensor[K,V], v2 : B=>tensor.Tensor[K,V], jj : CanJoin[A,B,K,V,V]) : BinaryUpdateOp[A,B,OpSet] = new BinaryUpdateOp[A,B,OpSet] { def opType = OpSet; override def apply(a : A, b : B) = { val _a = v1(a); jj.joinAll(a,b,(k,v1,v2) => _a(k) = v2); } } // uses a view to reduce its priority implicit def opUpdateTensorScalar[K,V1,V2,A,Op<:OpType] (implicit v1: A=>Tensor[K,V1], op : BinaryOp[V1,V2,Op,V1], s : Scalar[V2]) : BinaryUpdateOp[A,V2,Op] = new BinaryUpdateOp[A,V2,Op] { override def opType = op.opType; override def apply(a : A, b : V2) = { a.transformValues(v => op(v, b)); } } implicit def opSetTensorScalar[K,V:Scalar] : BinaryUpdateOp[Tensor[K,V],V,OpSet] = new BinaryUpdateOp[Tensor[K,V],V,OpSet] { def opType = OpSet; override def apply(a : Tensor[K,V], b : V) = { a.transformPairs((k,v) => b); } } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Tensor1.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.Domain1; import scalala.scalar.Scalar; /** * Implementation trait for mutable Tensor1 instances. * * @author dramage */ trait Tensor1Like [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +D<:Domain1[K], +This<:Tensor1[K,V]] extends tensor.Tensor1Like[K,V,D,This] with TensorLike[K,V,D,This]; /** * Mutable tensor.Tensor1. * * @author dramage */ trait Tensor1 [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] extends tensor.Tensor1[K,V] with Tensor[K,V] with Tensor1Like[K,V,Domain1[K],Tensor1[K,V]]; object Tensor1 { /** Constructs a closed-domain tensor for the given domain. */ def apply[K,V:Scalar](domain : Domain1[K]) = Tensor1Col(domain); } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Tensor1Col.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{Domain1,IndexDomain}; import scalala.scalar.Scalar; /** * Implementation trait for mutable Tensor1Col instances. * * @author dramage */ trait Tensor1ColLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +D<:Domain1[K], +This<:Tensor1Col[K,V]] extends tensor.Tensor1ColLike[K,V,D,This] with Tensor1Like[K,V,D,This] { override def t : Tensor1Row[K,V] = new Tensor1Row.View[K,V](repr); } /** * Mutable tensor.Tensor1Col. * * @author dramage */ trait Tensor1Col [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] extends tensor.Tensor1Col[K,V] with Tensor1[K,V] with Tensor1ColLike[K,V,Domain1[K],Tensor1Col[K,V]]; object Tensor1Col { /** Constructs a closed-domain tensor for the given domain. */ def apply[K,V:Scalar](domain : Domain1[K]) : Tensor1Col[K,V] = domain match { case d : IndexDomain => VectorCol(d); case _ => new Impl(domain, scala.collection.mutable.Map[K,V]()); } class Impl[K,V:Scalar]( override val domain : Domain1[K], override protected val data : scala.collection.mutable.Map[K,V]) extends Tensor.Impl[K,V](domain, data) with Tensor1Col[K,V]; class View[K,V](override val inner : Tensor1Row[K,V]) extends Tensor1Proxy[K,V,Tensor1Row[K,V]] with Tensor1Col[K,V] with Tensor1Like[K,V,Domain1[K],View[K,V]] { override def repr : View[K,V] = this; override def t : Tensor1Row[K,V] = inner; } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Tensor1Row.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{Domain1,IndexDomain}; import scalala.generic.collection.{CanSliceVector}; import scalala.scalar.Scalar; /** * Implementation trait for mutable Tensor1Row instances. * * @author dramage */ trait Tensor1RowLike [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V, +D<:Domain1[K], +This<:Tensor1Row[K,V]] extends tensor.Tensor1RowLike[K,V,D,This] with Tensor1Like[K,V,D,This] { override def t : Tensor1Col[K,V] = new Tensor1Col.View[K,V](repr); } /** * Mutable tensor.Tensor1Row. * * @author dramage */ trait Tensor1Row [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double) V] extends tensor.Tensor1Row[K,V] with Tensor1[K,V] with Tensor1RowLike[K,V,Domain1[K],Tensor1Row[K,V]]; object Tensor1Row { /** Constructs a closed-domain tensor for the given domain. */ def apply[K,V:Scalar](domain : Domain1[K]) : Tensor1Row[K,V] = domain match { case d : IndexDomain => VectorRow(d); case _ => new Impl(domain, scala.collection.mutable.Map[K,V]()); } class Impl[K,V:Scalar]( override val domain : Domain1[K], override protected val data : scala.collection.mutable.Map[K,V]) extends Tensor.Impl[K,V](domain, data) with Tensor1Row[K,V]; class View[K,V](override val inner : Tensor1Col[K,V]) extends Tensor1Proxy[K,V,Tensor1Col[K,V]] with Tensor1Row[K,V] with Tensor1Like[K,V,Domain1[K],View[K,V]] { override def repr : View[K,V] = this; override def t : Tensor1Col[K,V] = inner; } implicit def canSliceVectorRow[K, V:Scalar] = new CanSliceVector[Tensor[K,V], K, VectorRow[V]] { override def apply(from : Tensor[K,V], keys : Seq[K]) = new VectorRowSlice.FromKeySeq[K,V,Tensor[K,V]](from, keys); } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Tensor1Slice.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{IterableDomain,Domain1}; import scalala.scalar.Scalar; /** * Implementation trait for a Tensor1 view of a slice of keys from a Tensor. * * @author dramage */ trait Tensor1SliceLike [@specialized(Int,Long) K1, +D1<:IterableDomain[K1], @specialized(Int,Long) K2, +D2<:Domain1[K2], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K1,V], +This<:Tensor1Slice[K1,K2,V,Coll]] extends tensor.Tensor1SliceLike[K1,D1,K2,D2,V,Coll,This] with TensorSliceLike[K1, D1, K2, D2, V, Coll, This] with Tensor1Like[K2, V, D2, This]; /** * K Tensor1 view of a slice of keys from a Tensor. * * @author dramage */ trait Tensor1Slice [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K1,V]] extends tensor.Tensor1Slice[K1,K2,V,Coll] with TensorSlice[K1,K2,V,Coll] with Tensor1[K2,V] with Tensor1SliceLike[K1, IterableDomain[K1], K2, Domain1[K2], V, Coll, Tensor1Slice[K1, K2, V, Coll]]; object Tensor1Slice { /** This view is a no-op but is needed for correct implicit resolution. */ implicit def asTensor1[K,V](slice : Tensor1Slice[K,_,V,_]) : Tensor1[K,V] = slice; } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Tensor2.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{Domain1,Domain2,SetDomain,TableDomain}; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for a mutable tensor.Tensor2. * * @author dramage */ trait Tensor2Like [@specialized(Int) K1, @specialized(Int) K2, @specialized(Int,Long,Float,Double,Boolean) V, +D1<:Domain1[K1], +D2<:Domain1[K2], +D<:Domain2[K1,K2], +T<:Domain2[K2,K1], +This<:Tensor2[K1,K2,V]] extends tensor.Tensor2Like[K1,K2,V,D1,D2,D,T,This] with TensorLike[(K1,K2),V,D,This] { self => /** Updates the value indexed by (i,j). */ def update(i : K1, j : K2, value : V) : Unit; /** Fixed alias for update(i,j,value). */ /* final */ override def update(pos : (K1,K2), value : V) : Unit = update(pos._1, pos._2, value); /** Tranforms all key value pairs in this map by applying the given function. */ def transformTriples(f : (K1,K2,V)=>V) = transformPairs((k,v) => f(k._1, k._2, v)); override def t : Tensor2[K2,K1,V] = new Tensor2Transpose.Impl[K2,K1,V,This](repr) } /** * Mutable tensor.Tensor2. * * @author dramage */ trait Tensor2 [@specialized(Int) K1, @specialized(Int) K2, @specialized(Int,Long,Float,Double,Boolean) V] extends Tensor[(K1,K2),V] with tensor.Tensor2[K1,K2,V] with Tensor2Like[K1,K2,V,Domain1[K1],Domain1[K2],Domain2[K1,K2],Domain2[K2,K1],Tensor2[K1,K2,V]]; object Tensor2 { /** Constructs a closed-domain tensor for the given domain. */ def apply[K1,K2,V:Scalar](domain : Domain2[K1,K2]) : Tensor2[K1,K2,V] = domain match { case d : TableDomain => Matrix(d); case _ => new Impl(domain, scala.collection.mutable.Map[(K1,K2),V]()); } class Impl[K1,K2,V:Scalar] (override val domain : Domain2[K1,K2], protected override val data : scala.collection.mutable.Map[(K1,K2),V]) extends Tensor.Impl[(K1,K2),V](domain, data) with Tensor2[K1,K2,V] { override def apply(k1 : K1, k2 : K2) : V = { checkKey(k1,k2); data.getOrElse((k1,k2),scalar.zero); } override def update(k1 : K1, k2 : K2, value : V) = { checkKey(k1,k2); data.update((k1,k2), value); } } implicit def canSliceRow[T2<:Tensor2[K1,K2,V],K1,K2,V:Scalar] : CanSliceRow[T2,K1,Tensor1Row[K2,V]] = new CanSliceRow[T2,K1,Tensor1Row[K2,V]] { override def apply(from : T2, row : K1) = new RowSliceImpl[K1,K2,V,T2](from,row); } implicit def canSliceCol[K1,K2,V:Scalar] : CanSliceCol[Tensor2[K1,K2,V],K2,Tensor1Col[K1,V]] = new CanSliceCol[Tensor2[K1,K2,V],K2,Tensor1Col[K1,V]] { override def apply(from : Tensor2[K1,K2,V], col : K2) = new ColSliceImpl[K1,K2,V,Tensor2[K1,K2,V]](from, col); } implicit def canSliceMatrix[K1,K2,V:Scalar] : CanSliceMatrix[Tensor2[K1,K2,V],K1,K2,Matrix[V]] = new CanSliceMatrix[Tensor2[K1,K2,V],K1,K2,Matrix[V]] { override def apply(from : Tensor2[K1,K2,V], keys1 : Seq[K1], keys2 : Seq[K2]) = new MatrixSliceImpl[K1,K2,V,Tensor2[K1,K2,V]](from, keys1, keys2); } trait RowSliceLike[K1,K2,V,+Coll<:Tensor2[K1,K2,V],+This<:RowSlice[K1,K2,V,Coll]] extends tensor.Tensor2.RowSliceLike[K1,K2,V,Coll,This] with Tensor1SliceLike[(K1,K2),Domain2[K1,K2],K2,Domain1[K2],V,Coll,This] with Tensor1RowLike[K2,V,Domain1[K2],This]; trait RowSlice[K1,K2,V,+Coll<:Tensor2[K1,K2,V]] extends tensor.Tensor2.RowSlice[K1,K2,V,Coll] with Tensor1Slice[(K1,K2),K2,V,Coll] with Tensor1Row[K2,V] with RowSliceLike[K1,K2,V,Coll,RowSlice[K1,K2,V,Coll]]; class RowSliceImpl[K1,K2,V,+Coll<:Tensor2[K1,K2,V]] (override val underlying : Coll, override val row : K1) (implicit override val scalar : Scalar[V]) extends tensor.Tensor2.RowSliceImpl[K1,K2,V,Coll](underlying,row) with RowSlice[K1,K2,V,Coll]; trait ColSliceLike[K1,K2,V,+Coll<:Tensor2[K1,K2,V],+This<:ColSlice[K1,K2,V,Coll]] extends tensor.Tensor2.ColSliceLike[K1,K2,V,Coll,This] with Tensor1SliceLike[(K1,K2),Domain2[K1,K2],K1,Domain1[K1],V,Coll,This] with Tensor1ColLike[K1,V,Domain1[K1],This] trait ColSlice[K1,K2,V,+Coll<:Tensor2[K1,K2,V]] extends tensor.Tensor2.ColSlice[K1,K2,V,Coll] with Tensor1Slice[(K1,K2),K1,V,Coll] with Tensor1Col[K1,V] with ColSliceLike[K1,K2,V,Coll,ColSlice[K1,K2,V,Coll]]; class ColSliceImpl[K1,K2,V,+Coll<:Tensor2[K1,K2,V]] (override val underlying : Coll, override val col : K2) (implicit override val scalar : Scalar[V]) extends tensor.Tensor2.ColSliceImpl[K1,K2,V,Coll](underlying,col) with ColSlice[K1,K2,V,Coll]; trait MatrixSliceLike [@specialized(Int) K1, @specialized(Int) K2, @specialized(Int,Long,Float,Double,Boolean) V, +D1<:Domain1[K1], +D2<:Domain1[K2], +D<:Domain2[K1,K2], +T<:Domain2[K2,K1], +Coll<:Tensor2[K1,K2,V], +This<:MatrixSlice[K1,K2,V,Coll]] extends tensor.Tensor2.MatrixSliceLike[K1,K2,V,D1,D2,D,T,Coll,This] with TensorSliceLike[(K1,K2),D,(Int,Int),TableDomain,V,Coll,This] with MatrixLike[V,This] { override def update(i : Int, j : Int, value : V) = underlying.update(lookup1(i), lookup2(j), value); } trait MatrixSlice [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor2[K1,K2,V]] extends tensor.Tensor2.MatrixSlice[K1,K2,V,Coll] with TensorSlice[(K1,K2),(Int,Int),V,Coll] with Matrix[V] with MatrixSliceLike[K1,K2,V,Domain1[K1],Domain1[K2],Domain2[K1,K2],Domain2[K2,K1],Coll,MatrixSlice[K1,K2,V,Coll]]; class MatrixSliceImpl[K1, K2, V, +Coll<:Tensor2[K1,K2,V]] (override val underlying : Coll, override val keys1 : Seq[K1], override val keys2 : Seq[K2]) (implicit override val scalar : Scalar[V]) extends tensor.Tensor2.MatrixSliceImpl[K1,K2,V,Coll](underlying,keys1,keys2) with MatrixSlice[K1, K2, V, Coll]; } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Tensor2Transpose.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{Domain1,Domain2}; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for a transposed view of an underlying MutableTensor2. * * @author dramage */ trait Tensor2TransposeLike [@specialized(Int) K2, @specialized(Int) K1, @specialized(Int,Long,Float,Double,Boolean) V, +D2<:Domain1[K2], +D1<:Domain1[K1], +T<:Domain2[K2,K1], +D<:Domain2[K1,K2], +Coll<:Tensor2[K1,K2,V], +This<:Tensor2Transpose[K2,K1,V,Coll]] extends tensor.Tensor2TransposeLike[K2,K1,V,D2,D1,T,D,Coll,This] with TensorSliceLike[(K1,K2),D,(K2,K1),T,V,Coll,This] with Tensor2Like[K2,K1,V,D2,D1,T,D,This] { self => override def update(i : K2, j : K1, value : V) = underlying.update(j, i, value); override def t : Coll = underlying; } /** * Transposed view of an undelrying MutableTensor2. * * @author dramage */ trait Tensor2Transpose [@specialized(Int) K2, @specialized(Int) K1, @specialized(Int,Long,Float,Double,Boolean) V, +Coll <: Tensor2[K1,K2,V]] extends tensor.Tensor2Transpose[K2,K1,V,Coll] with TensorSlice[(K1,K2),(K2,K1),V,Coll] with Tensor2[K2,K1,V] with Tensor2TransposeLike[K2,K1,V,Domain1[K2],Domain1[K1],Domain2[K2,K1],Domain2[K1,K2],Coll,Tensor2Transpose[K2,K1,V,Coll]]; object Tensor2Transpose { /** Default implementation. */ class Impl[K2, K1, V:Scalar, +Coll <: Tensor2[K1,K2,V]](underlying : Coll) extends tensor.Tensor2Transpose.Impl[K2,K1,V,Coll](underlying) with Tensor2Transpose[K2,K1,V,Coll]; } ================================================ FILE: src/main/scala/scalala/tensor/mutable/TensorProxy.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{Domain1,IterableDomain,IndexDomain}; /** * Proxy for a mutable tensor. * * @author dramage */ trait TensorProxyLike [@specialized(Int, Long) K, @specialized(Int, Long, Float, Double, Boolean) V, +D<:IterableDomain[K], Inner <: Tensor[K,V], +This <: Tensor[K,V]] extends tensor.TensorProxyLike[K,V,D,Inner,This] with TensorLike[K,V,D,This] { override def update(key : K, value : V) : Unit = inner.update(key, value); override def transformPairs(f : (K,V)=>V) = inner.transformPairs(f); override def transformNonZeroPairs(fn : ((K,V)=>V)) : Boolean = inner.transformNonZeroPairs(fn); override def transformValues(f : V=>V) = inner.transformValues(f); override def transformNonZeroValues(fn : (V=>V)) = inner.transformNonZeroValues(fn); } /** * A proxy for a mutable Tensor. * * @author dramage */ trait TensorProxy[@specialized(Int,Long) A, @specialized(Int,Long,Float,Double,Boolean) B, Inner <: Tensor[A,B]] extends tensor.TensorProxy[A,B,Inner] with Tensor[A,B] with TensorProxyLike[A,B,IterableDomain[A],Inner,TensorProxy[A,B,Inner]]; /** * A proxy for a mutable Tensor1. * * @author dramage */ trait Tensor1ProxyLike [@specialized(Int, Long) K, @specialized(Int, Long, Float, Double, Boolean) V, +D<:Domain1[K], Inner <: Tensor1[K,V], +This <: Tensor1[K,V]] extends tensor.Tensor1ProxyLike[K,V,D,Inner,This] with TensorProxyLike[K,V,D,Inner,This] with Tensor1Like[K,V,D,This]; /** * A proxy for a mutable Tensor1. * * @author dramage */ trait Tensor1Proxy [@specialized(Int, Long) K, @specialized(Int, Long, Float, Double, Boolean) V, Inner <: Tensor1[K,V]] extends tensor.Tensor1Proxy[K,V,Inner] with TensorProxy[K,V,Inner] with Tensor1[K,V] with Tensor1ProxyLike[K,V,Domain1[K],Inner,Tensor1Proxy[K,V,Inner]]; /** * A proxy for a mutable Vector. * * @author dramage */ trait VectorProxyLike[@specialized(Int,Long,Float,Double) V, Inner<:Vector[V], +This<:Vector[V]] extends tensor.VectorProxyLike[V,Inner,This] with Tensor1ProxyLike[Int,V,IndexDomain,Inner,This] with VectorLike[V,This]; /** * A proxy for a mutable vector. * * @author dramage */ trait VectorProxy[@specialized(Int,Long,Float,Double) V, Inner<:Vector[V]] extends tensor.VectorProxy[V,Inner] with Tensor1Proxy[Int,V,Inner] with Vector[V] with VectorProxyLike[V,Inner,VectorProxy[V,Inner]]; ================================================ FILE: src/main/scala/scalala/tensor/mutable/TensorSlice.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain._; import scalala.scalar.Scalar; /** * Implementation trait for slices of an underlying Tensor. A slice * is a pass-through view of a (mapped) subset of the original Tensor's * domain. * * @author dramage */ trait TensorSliceLike [@specialized(Int,Long) K1, +D1<:IterableDomain[K1], @specialized(Int,Long) K2, +D2<:IterableDomain[K2], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K1,V], +This<:TensorSlice[K1,K2,V,Coll]] extends tensor.TensorSliceLike[K1,D1,K2,D2,V,Coll,This] with TensorLike[K2,V,D2,This] { override def update(key : K2, value : V) = underlying.update(lookup(key), value); } /** * Pass-through view of a (key-mapped) subset of an underlying Tensor. * * @author dramage */ trait TensorSlice [@specialized(Int,Long) K1, @specialized(Int,Long) K2, @specialized(Int,Long,Float,Double,Boolean) V, +Coll <: Tensor[K1, V]] extends tensor.TensorSlice[K1,K2,V,Coll] with Tensor[K2,V] with TensorSliceLike[K1, IterableDomain[K1], K2, IterableDomain[K2], V, Coll, TensorSlice[K1, K2, V, Coll]]; object TensorSlice { class FromKeyMap[K1, K2, V:Scalar, +Coll<:Tensor[K1, V]] (underlying : Coll, keymap : scala.collection.Map[K2,K1]) extends tensor.TensorSlice.FromKeyMap[K1,K2,V,Coll](underlying, keymap) with TensorSlice[K1,K2,V,Coll]; } ================================================ FILE: src/main/scala/scalala/tensor/mutable/Vector.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.IndexDomain; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for a Tensor that is also a tensor.Vector. * * @author dramage. */ trait VectorLike[@specialized(Int,Long,Float,Double,Boolean) V, +Repr<:Vector[V]] extends tensor.VectorLike[V,Repr] with Tensor1Like[Int,V,IndexDomain,Repr] { /** Returns a view of this vector as a row. Tightens bound superclass's return value. */ override def asRow : VectorRow[V] = this match { case r : VectorRow[_] => this.asInstanceOf[VectorRow[V]]; case _ => new VectorRow.View(repr); } /** Returns a view of this vector as a column. Tightens bound superclass's return value. */ override def asCol : VectorCol[V] = this match { case c : VectorCol[_] => this.asInstanceOf[VectorCol[V]]; case _ => new VectorCol.View(repr); } def := (seq : Seq[V]) = { checkDomain(IndexDomain(seq.length)); var i = 0; for (v <- seq) { this(i) = v; i += 1; } } def :=[O] (seq : Seq[O])(implicit tf : O=>V) = { checkDomain(IndexDomain(seq.length)); var i = 0; for (v <- seq) { this(i) = v; i += 1; } } /** In-place quick-sort of the values in this sequence. */ def sort(implicit ord : Ordering[V]) : Unit = quickSort(0, size); /** Adapted from scala.util.Sorting.sort1 */ private def quickSort[K](off: Int, len: Int)(implicit ord: Ordering[V]) { import ord._ val x = this; @inline def swap(a: Int, b: Int) { val t = x(a) x(a) = x(b) x(b) = t } @inline def vecswap(_a: Int, _b: Int, n: Int) { var a = _a var b = _b var i = 0 while (i < n) { swap(a, b) i += 1 a += 1 b += 1 } } @inline def med3(a: Int, b: Int, c: Int) = { if (x(a) < x(b)) { if (x(b) < x(c)) b else if (x(a) < x(c)) c else a } else { if (x(b) > x(c)) b else if (x(a) > x(c)) c else a } } @inline def sort2(off: Int, len: Int) { // Insertion sort on smallest arrays if (len < 7) { var i = off while (i < len + off) { var j = i while (j > off && x(j-1) > x(j)) { swap(j, j-1) j -= 1 } i += 1 } } else { // Choose a partition element, v var m = off + (len >> 1) // Small arrays, middle element if (len > 7) { var l = off var n = off + len - 1 if (len > 40) { // Big arrays, pseudomedian of 9 var s = len / 8 l = med3(l, l+s, l+2*s) m = med3(m-s, m, m+s) n = med3(n-2*s, n-s, n) } m = med3(l, m, n) // Mid-size, med of 3 } val v = x(m) // Establish Invariant: v* (v)* v* var a = off var b = a var c = off + len - 1 var d = c var done = false while (!done) { while (b <= c && x(b) <= v) { if (x(b) == v) { swap(a, b) a += 1 } b += 1 } while (c >= b && x(c) >= v) { if (x(c) == v) { swap(c, d) d -= 1 } c -= 1 } if (b > c) { done = true } else { swap(b, c) c -= 1 b += 1 } } // Swap partition elements back to middle val n = off + len var s = math.min(a-off, b-a) vecswap(off, b-s, s) s = math.min(d-c, n-d-1) vecswap(b, n-s, s) // Recursively sort non-partition-elements s = b - a if (s > 1) sort2(off, s) s = d - c if (s > 1) sort2(n-s, s) } } sort2(off, len) } } /** * A Vector is a Tensor indexed by Ints on the IndexDomain. * * @author dramage */ trait Vector[@specialized(Int,Long,Float,Double,Boolean) V] extends tensor.Vector[V] with Tensor1[Int,V] with VectorLike[V,Vector[V]]; object Vector extends dense.DenseVectorConstructors; ================================================ FILE: src/main/scala/scalala/tensor/mutable/VectorCol.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.IndexDomain; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for mutable VectorCol instances. * * @author dramage */ trait VectorColLike[@specialized(Int,Long,Float,Double) V, +This<:VectorCol[V]] extends tensor.VectorColLike[V,This] with Tensor1ColLike[Int,V,IndexDomain,This] with VectorLike[V,This] { override def t : VectorRow[V] = new VectorRow.View[V](repr); } /** * Mutable tensor.VectorCol. * * @author dramage */ trait VectorCol[@specialized(Int,Long,Float,Double) V] extends tensor.VectorCol[V] with Tensor1Col[Int,V] with Vector[V] with VectorColLike[V,VectorCol[V]]; object VectorCol { def apply[V:Scalar](domain : IndexDomain) = dense.DenseVectorCol[V](domain); class View[V](override val inner : Vector[V]) extends VectorProxy[V,Vector[V]] with tensor.VectorProxy[V,Vector[V]] with VectorCol[V] with VectorLike[V,View[V]] { override def repr : View[V] = this; } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/VectorRow.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.IndexDomain; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for mutable VectorRow instances. * * @author dramage */ trait VectorRowLike[@specialized(Int,Long,Float,Double) V, +This<:VectorRow[V]] extends tensor.VectorRowLike[V,This] with Tensor1RowLike[Int,V,IndexDomain,This] with VectorLike[V,This] { override def t : VectorCol[V] = new VectorCol.View[V](repr); } /** * Mutable tensor.VectorRow. * * @author dramage */ trait VectorRow[@specialized(Int,Long,Float,Double) V] extends tensor.VectorRow[V] with Tensor1Row[Int,V] with Vector[V] with VectorRowLike[V,VectorRow[V]]; object VectorRow { def apply[V:Scalar](domain : IndexDomain) = dense.DenseVectorRow[V](domain); class View[V](override val inner : Vector[V]) extends VectorProxy[V,Vector[V]] with tensor.VectorProxy[V,Vector[V]] with VectorRow[V] with VectorLike[V,View[V]] { override def repr : View[V] = this; } } ================================================ FILE: src/main/scala/scalala/tensor/mutable/VectorSlice.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package mutable; import domain.{IterableDomain,IndexDomain}; import scalala.scalar.Scalar; import scalala.generic.collection._; import scalala.operators._; /** * Implementation trait for a Vector-like view of a mutable Tensor. * * @author dramage */ trait VectorSliceLike [@specialized(Int,Long) K, +D<:IterableDomain[K], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K,V], +This<:VectorSlice[K,V,Coll]] extends tensor.VectorSliceLike[K, D, V, Coll, This] with Tensor1SliceLike[K, D, Int, IndexDomain, V, Coll, This] with VectorLike[V, This]; /** * Vector-like view of a mutable Tensor. * * @author dramage */ trait VectorSlice [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K, V]] extends tensor.VectorSlice[K,V,Coll] with Tensor1Slice[K,Int,V,Coll] with Vector[V] with VectorSliceLike[K, IterableDomain[K], V, Coll, VectorSlice[K, V, Coll]]; /** * Implementation trait for a VectorRow-like view of a mutable Tensor. * * @author dramage */ trait VectorRowSliceLike [@specialized(Int,Long) K, +D<:IterableDomain[K], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K,V], +This<:VectorRowSlice[K,V,Coll]] extends tensor.VectorRowSliceLike[K, D, V, Coll, This] with VectorSliceLike[K, D, V, Coll, This] with VectorRowLike[V, This]; /** * VectorRow-like view of a mutable Tensor. * * @author dramage */ trait VectorRowSlice [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K, V]] extends tensor.VectorRowSlice[K,V,Coll] with VectorSlice[K,V,Coll] with VectorRow[V] with VectorRowSliceLike[K, IterableDomain[K], V, Coll, VectorRowSlice[K, V, Coll]]; object VectorRowSlice { class FromKeySeq[K, V:Scalar, +Coll<:Tensor[K, V]] (underlying : Coll, keys : Seq[K]) extends tensor.VectorRowSlice.FromKeySeq[K,V,Coll](underlying, keys) with VectorRowSlice[K,V,Coll]; } /** * Implementation trait for a VectorCol-like view of a mutable Tensor. * * @author dramage */ trait VectorColSliceLike [@specialized(Int,Long) K, +D<:IterableDomain[K], @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K,V], +This<:VectorColSlice[K,V,Coll]] extends tensor.VectorColSliceLike[K, D, V, Coll, This] with VectorSliceLike[K, D, V, Coll, This] with VectorColLike[V, This]; /** * VectorCol-like view of a mutable Tensor. * * @author dramage */ trait VectorColSlice [@specialized(Int,Long) K, @specialized(Int,Long,Float,Double,Boolean) V, +Coll<:Tensor[K, V]] extends tensor.VectorColSlice[K,V,Coll] with VectorSlice[K,V,Coll] with VectorCol[V] with VectorColSliceLike[K, IterableDomain[K], V, Coll, VectorColSlice[K, V, Coll]]; object VectorColSlice { class FromKeySeq[K, V:Scalar, +Coll<:Tensor[K, V]] (underlying : Coll, keys : Seq[K]) extends tensor.VectorColSlice.FromKeySeq[K,V,Coll](underlying, keys) with VectorColSlice[K,V,Coll]; } ================================================ FILE: src/main/scala/scalala/tensor/package.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package object tensor { } ================================================ FILE: src/main/scala/scalala/tensor/sparse/SparseArrayTensor.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package sparse; import domain.{DomainLike,IterableDomain}; import scalala.collection.sparse.SparseArray; import scalala.scalar.Scalar; /** * Implementation trait for a tensor backed by a sparse array of values. * * @author dramage */ trait SparseArrayTensorLike [@specialized(Int,Long) A, @specialized(Int,Long,Float,Double,Boolean) B, +D<:IterableDomain[A] with DomainLike[A,D], +This<:SparseArrayTensor[A,B]] extends mutable.TensorLike[A,B,D,This] { def data : SparseArray[B]; override def nonzeroSize = data.activeLength; /** Assigns the given value to all elements of this map. */ def :=(value : B) = { if (value == data.default) { data.clear; } else { var i = 0; while (i < data.length) { data(i) = value; i += 1; } } } /** Tranforms all values in this map by applying the given function. */ override def transformValues(f : B=>B) = data.transform(f); } /** * Mutable tensor by a sparse array of values. * * @author dramage */ trait SparseArrayTensor [@specialized(Int,Long) A, @specialized(Int,Long,Float,Double,Boolean) B] extends mutable.Tensor[A,B] with SparseArrayTensorLike[A,B,IterableDomain[A],SparseArrayTensor[A,B]]; ================================================ FILE: src/main/scala/scalala/tensor/sparse/SparseVector.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package sparse; import domain.{IterableDomain,IndexDomain}; import scalala.collection.sparse.{SparseArray,DefaultArrayValue}; import scalala.scalar.Scalar; import scalala.operators._ import scalala.generic.collection.{CanCopy, CanCreateZerosLike, CanSliceCol, CanAppendColumns} import dense.DenseVector ; /** * A vector backed by a SparseArray. * * @author dramage */ @SerialVersionUID(1) trait SparseVector[@specialized(Int,Long,Float,Double) V] extends SparseArrayTensor[Int,V] with SparseArrayTensorLike[Int,V,IndexDomain,SparseVector[V]] with mutable.Vector[V] with mutable.VectorLike[V,SparseVector[V]] with Serializable { override def length = data.length; override def apply(key : Int) = data(key); override def update(key : Int, value : V) = data(key) = value; override def foreachNonZeroKey[U](fn : (Int=>U)) = { data.foreachActiveKey(fn); data.activeLength == data.length; } override def foreachNonZeroValue[U](fn : (V=>U)) = { data.foreachActiveValue(fn); data.activeLength == data.length; } override def foreachNonZeroPair[U](fn : ((Int,V)=>U)) = { data.foreachActivePair(fn); data.activeLength == data.length; } override def pairsIteratorNonZero:Iterator[(Int,V)] = data.activeIterator } object SparseVector { /** Creates a sparse vector literal. */ def apply[V:Scalar:ClassManifest:DefaultArrayValue](values : V*) = new SparseVectorCol(SparseArray(values :_*)) /** Returns a vector of zeros of the given size. */ def zeros[V:Scalar:ClassManifest:DefaultArrayValue](size : Int) = create(size)(); /** Creates a sparse vector of the given size with given initial values. */ def create[V:Scalar:ClassManifest:DefaultArrayValue](size : Int)(values : (Int,V)*) = new SparseVectorCol(SparseArray.create(size)(values :_*)); /** Tabulate a vector with the value at each offset given by the function. */ def tabulate[V:Scalar:ClassManifest:DefaultArrayValue](size : Int)(f : (Int => V)) = new SparseVectorCol(SparseArray.tabulate(size)(f)); /* * Implicits for functions */ /** Optimized base class for creating zeros */ trait CanCreateZerosSparseVector [@specialized V, @specialized RV, SV[V]<:SparseVector[V]] extends CanCreateZerosLike[SV[V],SV[RV]] { def create(length : Int) : SV[RV]; def apply(v1: SV[V]) = create(v1.length); } class GenericSparseVectorRowBase[@specialized V:Scalar:Manifest:DefaultArrayValue] { def create(length : Int) = new SparseVectorRow(new SparseArray[V](length)) } class GenericSparseVectorColBase[@specialized V:Scalar:Manifest:DefaultArrayValue] { def create(length : Int) = new SparseVectorCol(new SparseArray[V](length)) } class GenericSparseVectorBase[@specialized V:Scalar:Manifest:DefaultArrayValue] { def create(length : Int) = new SparseVectorCol(new SparseArray[V](length)) } implicit def canCreateZerosSparseVector[@specialized V, @specialized RV:Scalar:Manifest:DefaultArrayValue] : CanCreateZerosSparseVector[V, RV, SparseVector] = new GenericSparseVectorColBase with CanCreateZerosSparseVector[V, RV, SparseVector]; /** Optimized base class for mapping dense columns. */ implicit def canCreateZerosSparseVectorCols[@specialized V, @specialized RV:Scalar:Manifest:DefaultArrayValue] : CanCreateZerosSparseVector[V, RV, SparseVectorCol] = new GenericSparseVectorColBase with CanCreateZerosSparseVector[V, RV, SparseVectorCol]; /** Optimized base class for mapping dense rows. */ implicit def canCreateZerosSparseVectorRows[@specialized V, @specialized RV:Scalar:Manifest:DefaultArrayValue] : CanCreateZerosSparseVector[V, RV, SparseVectorRow] = new GenericSparseVectorRowBase with CanCreateZerosSparseVector[V, RV, SparseVectorRow]; /** Optimized base class for mapping sparse columns. */ implicit def canCopySparseVectorCols[@specialized V:Scalar:Manifest] = new CanCopySparseVectorCol[V]; /** Optimized base class for mapping sparse rows. */ implicit def canCopySparseVectorRows[@specialized V:Scalar:Manifest] = new CanCopySparseVectorRow[V]; /** Optimized base class for mapping sparse . */ implicit def canCopySparseVector[@specialized V:Scalar:Manifest] = new CanCopySparseVector[V]; /** Optimized base class for copying sparse */ class CanCopySparseVectorRow[@specialized V:Scalar:ClassManifest] extends CanCopy[SparseVectorRow[V]] { def apply(v1: SparseVectorRow[V]) = { new SparseVectorRow[V](v1.data.copy) } } class CanCopySparseVector[@specialized V:Scalar:ClassManifest] extends CanCopy[SparseVector[V]] { def apply(v1: SparseVector[V]) = { new SparseVectorCol[V](v1.data.copy) } } class CanCopySparseVectorCol[@specialized V:Scalar:ClassManifest] extends CanCopy[SparseVectorCol[V]] { def apply(v1: SparseVectorCol[V]) = { new SparseVectorCol[V](v1.data.copy) } } /* Implicits for operations */ implicit object SparseVectorDInnerMulSparseVectorD extends BinaryOp[SparseVectorRow[Double],SparseVectorCol[Double],OpMulRowVectorBy,Double] { override def opType = OpMulRowVectorBy; override def apply(a : SparseVectorRow[Double], b : SparseVectorCol[Double]) = { require(a.length == b.length, "Vectors must have same length"); a dot b } } implicit object SparseVectorDDotSparseVectorD extends BinaryOp[SparseVector[Double],SparseVector[Double],OpMulInner,Double] { override def opType = OpMulInner; override def apply(a : SparseVector[Double], b : SparseVector[Double]) = { require(a.length == b.length, "Vectors must have same length"); val aData = a.data val bData = b.data val activeA = aData.activeLength val activeB = bData.activeLength var sum = 0.0 var ai = 0 var bi = 0 while(ai < activeA) { while(bi < activeB && bData.indexAt(bi) < aData.indexAt(ai)) bi += 1 if(bi < activeB && bData.indexAt(bi) == aData.indexAt(ai)) sum += bData.valueAt(bi) * aData.valueAt(ai) ai += 1 } sum } } implicit object SparseVectorDDotDenseVectorD extends BinaryOp[SparseVector[Double],DenseVector[Double],OpMulInner,Double] { override def opType = OpMulInner; override def apply(a : SparseVector[Double], b : DenseVector[Double]) = { require(a.length == b.length, "Vectors must have same length"); val aData = a.data val bData = b.data val activeA = aData.activeLength val bStep = b.stride var sum = 0.0 var ai = 0 var bPos = 0 while(ai < activeA) { val aIndex = aData.indexAt(ai) bPos = bStep * aIndex + b.offset sum += bData(bPos) * aData.valueAt(ai) ai += 1 } sum } } implicit object DenseVectorDDotSparseVectorD extends BinaryOp[DenseVector[Double],SparseVector[Double],OpMulInner,Double] { override def opType = OpMulInner; override def apply(a : DenseVector[Double], b : SparseVector[Double]) = { require(a.length == b.length, "Vectors must have same length"); b dot a } } implicit object VectorDAddSparseVectorDInto extends BinaryUpdateOp[mutable.Vector[Double],SparseVector[Double],OpAdd] { override def opType = OpAdd; override def apply(a : mutable.Vector[Double], b : SparseVector[Double]) { require(a.length == b.length, "Vectors must have same length"); val bIndex = b.data.indexArray val bData = b.data.rawValueArray val activeB = b.data.activeLength var bi = 0 while(bi < activeB) { a(bIndex(bi)) += bData(bi) bi += 1 } } } implicit object SparseVectorDMulDoubleInto extends BinaryUpdateOp[SparseVector[Double],Double,OpMul] { override def opType = OpMul; override def apply(a : SparseVector[Double], b : Double) { val bData = a.data.rawValueArray val activeB = a.data.activeLength var bi = 0 while(bi < activeB) { bData(bi) *= b bi += 1 } } } implicit object VectorDSubSparseVectorDInto extends BinaryUpdateOp[mutable.Vector[Double],SparseVector[Double],OpSub] { override def opType = OpSub; override def apply(a : mutable.Vector[Double], b : SparseVector[Double]) { require(a.length == b.length, "Vectors must have same length"); val bIndex = b.data.indexArray val bData = b.data.rawValueArray val activeB = b.data.activeLength var bi = 0 while(bi < activeB) { a(bIndex(bi)) -= bData(bi) bi += 1 } } } implicit def binaryOpFromBinaryUpdateOp[SV<:SparseVector[Double],Other,Op<:OpType](implicit copy: CanCopy[SV], op: BinaryUpdateOp[SV,Other,Op]) = { new BinaryOp[SV,Other,Op,SV] { override def opType = op.opType; override def apply(a : SV, b : Other) = { val c = copy(a) op(c,b) c } } } implicit val vspace = scalala.operators.bundles.MutableInnerProductSpace.make[Double,scalala.tensor.sparse.SparseVector[Double]] } class SparseVectorRow[@specialized(Int,Long,Float,Double) V] (override val data : SparseArray[V]) (implicit override val scalar : Scalar[V]) extends SparseVector[V] with mutable.VectorRow[V] with mutable.VectorRowLike[V,SparseVectorRow[V]] { override def newBuilder[K2,V2:Scalar](domain : IterableDomain[K2]) = { implicit val mf = implicitly[Scalar[V2]].manifest; implicit val dv = implicitly[Scalar[V2]].defaultArrayValue; domain match { case that : IndexDomain => new SparseVectorRow(new SparseArray[V2](that.size)).asBuilder; case _ => super.newBuilder[K2,V2](domain); } } override def t : SparseVectorCol[V] = new SparseVectorCol(data)(scalar); } /** * SparseVectors as a column. * * @author dramage */ class SparseVectorCol[@specialized(Int,Long,Float,Double) V] (override val data : SparseArray[V]) (implicit override val scalar : Scalar[V]) extends SparseVector[V] with mutable.VectorCol[V] with mutable.VectorColLike[V,SparseVectorCol[V]] { override def newBuilder[K2,V2:Scalar](domain : IterableDomain[K2]) = { implicit val mf = implicitly[Scalar[V2]].manifest; implicit val dv = implicitly[Scalar[V2]].defaultArrayValue; domain match { case that : IndexDomain => new SparseVectorCol(new SparseArray[V2](that.size)).asBuilder; case _ => super.newBuilder[K2,V2](domain); } } override def t : SparseVectorRow[V] = new SparseVectorRow(data)(scalar); } ================================================ FILE: src/test/scala/scalala/collection/sparse/SparseArrayTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.collection.sparse; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith @RunWith(classOf[JUnitRunner]) class SparseArrayTest extends FunSuite with Checkers { test("Map") { val x = SparseArray(1,0,2,0,3,0,-1,-2,-3); x.compact; val y = x.map(_ + 1); assert(x.length === y.length); assert(x.activeLength === x.length - 3); assert(y.activeLength === y.length - 1); assert(y.toList === List(2,1,3,1,4,1,0,-1,-2)); } test("Filter") { val x = SparseArray(1,0,2,0,3,0,-1,-2,-3); x.compact; assert(x.filter(_ % 2 == 1).toList === List(1,3)); assert(x.filter(_ % 2 == 1).activeLength === 2); assert(x.filter(_ % 2 == 0).toList === List(0,2,0,0,-2)); assert(x.filter(_ % 2 == 0).activeLength === 2); assert(x.filter(_ > 0).toList === List(1,2,3)); assert(x.filter(_ > 0).activeLength === 3); assert(x.filter(_ >= 0).toList === List(1,0,2,0,3,0)); assert(x.filter(_ >= 0).activeLength === 3); val y = SparseArray(0,1,0,0,-1,-2,-3,-5); y.compact; assert(y.filter(_ > 0).toList === List(1)); assert(y.filter(_ >= 0).toList === List(0,1,0,0)); } } ================================================ FILE: src/test/scala/scalala/generic/CanAssignIntoTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith @RunWith(classOf[JUnitRunner]) class CanAssignIntoTest extends FunSuite with Checkers { import operators.Implicits._; test("Array[Int]") { val a = Array(0,0,0); val aRef = a; val b = Array(1,2,3); val bRef = b; a := b; assert(a.toList === b.toList); assert(!(a eq b)); assert((a eq aRef)); assert((b eq bRef)); } test("Array[Array[Int]]") { val a = Array(Array(0,0),Array(0,0),Array(0,0)); val aRef = a; val b = Array(Array(1,2),Array(3,4),Array(5,6)); val bRef = b; a := b; assert(a.map(_.toList).toList === b.map(_.toList).toList); assert(!(a eq b)); assert((a zip b).forall(tup => !(tup._1 eq tup._2))); assert((a eq aRef)); assert((b eq bRef)); } } ================================================ FILE: src/test/scala/scalala/generic/collection/CanGetDoubleTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith; @RunWith(classOf[JUnitRunner]) class CanGetDoubleTest extends FunSuite with Checkers { def get[Coll,K](coll : Coll, k : K)(implicit get : CanGetDouble[Coll,K]) = get(coll, k); test("array") { assert(get(Array(1,2,3),1) === 2.0); } test("map") { assert(get(Map('a'->1,'b'->2), 'b') === 2.0); } } ================================================ FILE: src/test/scala/scalala/generic/collection/CanGetValueTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith; @RunWith(classOf[JUnitRunner]) class CanGetValueTest extends FunSuite with Checkers { def get[Coll,K,V](coll : Coll, k : K)(implicit get : CanGetValue[Coll,K,V]) = get(coll, k); test("array") { assert(get(Array(1.0,2.0,3.0),1) === 2.0); } test("map") { assert(get(Map('a'->1,'b'->2), 'b') === 2); } } ================================================ FILE: src/test/scala/scalala/generic/collection/CanMapValuesTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package generic; package collection; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith; @RunWith(classOf[JUnitRunner]) class CanMapValuesTest extends FunSuite with Checkers { def toDoubles[From,A,To](coll : From)(implicit map : CanMapValues[From,A,Double,To], cv : A=>Double) = map.map(coll, cv); test("array") { assert(toDoubles(Array(1,2,3)).toList === List(1.0,2.0,3.0)); } test("map") { assert(toDoubles(scala.collection.Map('a'->2,'b'->3)) === Map('a'->2.0,'b'->3.0)); } } ================================================ FILE: src/test/scala/scalala/library/LibraryTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra * * Copyright (C) 2008- Daniel Ramage * * This library is free software you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala package library import org.scalatest._ import matchers.ShouldMatchers import org.scalatest.junit._ import org.scalatest.prop._ import org.junit.runner.RunWith import scalala.scalar.Complex import scalala.tensor.mutable.{Matrix, Vector} import Library._ import tensor.dense.{DenseVector, DenseMatrix} @RunWith(classOf[JUnitRunner]) class LibraryTest extends FunSuite with Checkers with ShouldMatchers { test("log") { assert(log(2.8) === 1.0296194171811581) assert(log(1) === 0) assert(log(Array(1,2,3,4)).toList === List(0.0, 0.6931471805599453, 1.0986122886681098, 1.3862943611198906)) assert(log(DenseVector(1,2,3,4)) === DenseVector(0.0, 0.6931471805599453, 1.0986122886681098, 1.3862943611198906)) assert(log(DenseMatrix((1,2,3,4))) === DenseMatrix((0.0, 0.6931471805599453, 1.0986122886681098, 1.3862943611198906))) } test("mean") { assert(mean(List(Array(0,2),Array(2,4))).toList === List(1,3)) assert(mean(List(Array(1.0,3.0),Array(2.0,4.0))).toList === List(1.5,3.5)) assert(mean(Iterator(1,2,3)) === 2.0) assert(mean(List(1,2,3,4)) === ((1+2+3+4) / 4.0)) } test("stddev") { assert(stddev(Array(1,2,3)) === 1.0) assert(stddev(Iterator(1,2,3,4)) === 1.2909944487358056) } test("sum") { assert(sum(Matrix((0,2),(2,4))).toList === List(2,6)) assert(sum(Matrix((1.0,3.0),(2.0,4.0))).toList === List(3,7)) assert(sum(Matrix((1.0,3.0),(2.0,4.0)),Axis.Vertical).toList === List(4,6)) } test("exp") { exp(1.0296194171811581) should be (2.8) exp(0) should be (1) exp(Array(0.0, 0.6931471805599453, 1.0986122886681098, 1.3862943611198906)) should equal (Array(1,2,3,4)) exp(DenseVector(0.0, 0.6931471805599453, 1.0986122886681098, 1.3862943611198906)).toList should equal (List(1,2,3,4)) exp(DenseMatrix((0.0, 0.6931471805599453, 1.0986122886681098, 1.3862943611198906))) should equal (DenseMatrix((1,2,3,4))) } test("Complex:exp") { // exp(0 + 0i) assert(exp(Complex(0,0)) === Complex(1,0)) // exp(0 + Pi * i / 2) val t1 = exp(Complex(0, math.Pi / 2)) t1.real should be (0.0 plusOrMinus 1e-10) t1.imag should be (1.0 plusOrMinus 1e-10) // exp(5 + 7i) val t2 = exp(Complex(5, 7)) t2.real should be (111.889 plusOrMinus 1e-3) t2.imag should be (97.505 plusOrMinus 1e-3) } test("Tensor:Norm") { val v = Array(-0.4326, -1.6656, 0.1253, 0.2877, -1.1465) norm(v, 1) should be (3.6577 plusOrMinus 1e-4) norm(v, 2) should be (2.0915 plusOrMinus 1e-4) norm(v, 3) should be (1.8405 plusOrMinus 1e-4) norm(v, 4) should be (1.7541 plusOrMinus 1e-4) norm(v, 5) should be (1.7146 plusOrMinus 1e-4) norm(v, 6) should be (1.6940 plusOrMinus 1e-4) norm(v, Double.PositiveInfinity) should be (1.6656 plusOrMinus 1e-4) } test("Tensor:Normalize") { val v = DenseVector(-0.4326, -1.6656, 0.1253, 0.2877, -1.1465) val norm2V = normalize(v, 2) val norm1V = normalize(v, 1) norm(norm2V, 2) should be (1.0 plusOrMinus 1e-4) norm(norm1V, 1) should be (1.0 plusOrMinus 1e-4) } test("Tensor:LogNormalize") { val v = DenseVector(-0.4326, -1.6656, 0.1253, 0.2877, -1.1465) val normed = logNormalize(v) softmax(normed) should be (0.0 plusOrMinus 1e-4) } test("Matrix:Mean") { val X = Matrix((9,5,14,4),(2,-12,8,-5),(8,-6,-8,11)) val meanV = Vector(6.3333, -4.3333, 4.6666, 3.3333) val meanH = Vector(8., -1.75, 1.25) assert(mean(X, Axis.Horizontal) forallPairs ((i, v) => math.abs(v-meanH(i)) < 1e-4)) assert(mean(X, Axis.Vertical) forallPairs ((i, v) => math.abs(v-meanV(i)) < 1e-4)) } test("Matrix:Covariance") { val X = Matrix((9.,5.,14.,4.),(2.,-12.,8.,-5.),(8.,-6.,-8.,11.)) val mu = Vector(8., -1.75, 1.25) val Sigma = Matrix(( 20.6666, 35.3333, -22.0000), ( 35.3333, 74.9166, -7.4166), (-22.0000, -7.4166, 92.9166)) val (chkSigmaH, chkMuH) = covariance(X, Axis.Horizontal) assert(chkMuH forallPairs ((i, v) => math.abs(v-mu(i)) < 1e-4)) assert(chkSigmaH forallPairs ((idx, v) => math.abs(v-Sigma(idx)) < 1e-4)) val (chkSigmaV, chkMuV) = covariance(X.t, Axis.Vertical) assert(chkMuV forallPairs ((i, v) => math.abs(v-mu(i)) < 1e-4)) assert(chkSigmaV forallPairs ((idx, v) => math.abs(v-Sigma(idx)) < 1e-4)) } test("Matrix:MinMax") { val X = Matrix((9.,5.,14.,4.),(2.,-12.,8.,-5.),(8.,-6.,-8.,11.)) min(X, Axis.Horizontal).toArray should be === (Array(4.,-12.,-8.)) max(X, Axis.Horizontal).toArray should be === (Array(14.,8.,11.)) min(X, Axis.Vertical).toArray should be === (Array(2.,-12.,-8.,-5.)) max(X, Axis.Vertical).toArray should be === (Array(9.,5.,14.,11.)) } } ================================================ FILE: src/test/scala/scalala/library/LinearAlgebraTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package library; import org.scalacheck.{Arbitrary,Gen} import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.scalatest.matchers.ShouldMatchers; import org.junit.runner.RunWith; import scalala.tensor.dense.DenseVector import scalala.tensor.mutable.{Matrix,Vector} import scalala.library.LinearAlgebra._; @RunWith(classOf[JUnitRunner]) class LinearAlgebraTest extends FunSuite with Checkers with ShouldMatchers { test("kron") { val a = Matrix((1,2),(3,4)); val b = Matrix((0,5),(6,7)); assert(kron(a,b) === Matrix((0,5,0,10),(6,7,12,14),(0,15,0,20),(18,21,24,28))); } test("ranks") { assert(ranks(Array(1,2,3)).toList === List(1.0,2.0,3.0)); assert(ranks(Array(3,-1,2)).toList === List(3.0,1.0,2.0)); assert(ranks(Array(1,2,3,3)).toList === List(1.0,2.0,3.5,3.5)); assert(ranks(Array(1,2,3,3,3)).toList === List(1.0,2.0,4.0,4.0,4.0)); } test("cholesky") { val A = Matrix((1.,0.,0.),(2.,3.,0.),(4.,5.,6.)) val Sigma = A * A.t assert(cholesky(Sigma) === A) } test("eigSym") { val A = Matrix((9.,0.,0.),(0.,82.,0.),(0.,0.,25.)) val (lambda, Some(evs)) = eigSym(A, true) assert(lambda === Vector(9.,25.,82.)) assert(evs === Matrix((1.,0.,0.),(0.,0.,1.),(0.,1.,0.))) } test("LUfactorization") { val (m, _) = LU(Matrix(( 29, 42, -4, 50, 1), ( 20,-31, 32, 21, 2), (-47,-20, 24,-22, 3), ( 3, 17,-45, 23, 4))) val aux = Matrix((-47.0000, -20.0000, 24.0000, -22.0000, 3.0000), ( -0.4255, -39.5106, 42.2127, 11.6382, 3.2765), ( -0.6170, -0.7506, 42.4964, 45.1620, 5.3107), ( -0.0638, -0.3979, -0.6275, 54.5694, 8.8282)) assert(m forallPairs ((idx,v) => math.abs(v-aux(idx)) < 1e-4)) } test("det") { val A = Matrix((9,26,21),(48,3,11),(7,48,26)) det(A) should be (13446.99999999 plusOrMinus 1e-8) val B = Matrix((1,2,3),(4,5,-6),(7,8,9)) det(B) should be (-72.0 plusOrMinus 1e-15) val C = Matrix((1,2,3),(2,4,6),(0,-1,0)) // 1st and 2nd row linearly dep. det(C) should be (0.0 plusOrMinus 1e-15) val D = Matrix((-1,1,-1),(1,2,3),(3,-10,1)) det(D) should be (-8.0 plusOrMinus 1e-8) } test("inv") { val X = Matrix(( 29, 42, -4, 50), ( 20,-31, 32, 21), (-47,-20, 24,-22), ( 3, 17,-45, 23)) val I = Matrix.eye[Double](4) assert((inv(X) * X) forallPairs ((idx,v) => math.abs(v-I(idx)) < 1e-15)) } test("pinv") { val X = Matrix((54, 95), (23, 25), (70, 41), (31, 19)) val I = Matrix.eye[Double](2) assert((pinv(X) * X) forallPairs ((idx,v) => math.abs(v-I(idx)) < 1e-15)) } test("cross") { // specific example; with prime elements val (v1, v2, r) = (DenseVector(13, 3, 7), DenseVector(5, 11, 17), DenseVector(-26, -186, 128)) assert(cross(v1, v2) === r) assert(cross(v2, v1) === r * -1) // test using a re-write of the cross-product equation and a scalacheck arbitrary generator implicit def arb3DVector: Arbitrary[DenseVector[Double]] = Arbitrary { for { els <- Gen.containerOfN[Array, Double](3, Gen.chooseNum[Double](-100.0, 100.0)) } yield DenseVector(els(0), els(1), els(2)) } check {(a: DenseVector[Double], b: DenseVector[Double]) => val r = DenseVector( a(1) * b(2) - a(2) * b(1), a(2) * b(0) - a(0) * b(2), a(0) * b(1) - a(1) * b(0)) cross(a, b) == r cross(b, a) == r * -1.0 } // test the failure that should occur if a or b does not have 3 components val v4comp = DenseVector(1,2,3,4) intercept[IllegalArgumentException] { cross(v4comp, v4comp) } } test("rank") { val r1 = Matrix((1.,2.,3.), (1.,2.,3.), (1.,2.,3.)) // rank 1 matrix val r2 = Matrix((1.,2.,3.), (4.,5.,6.), (7.,8.,9.)) // rank 2 matrix val r3 = Matrix((1.,2.,3.), (4.,5.,6.), (6.,8.,9.)) // rank 3 matrix assert(rank(r1) === 1) assert(rank(r2) === 2) assert(rank(r3) === 3) } test("qr") { val A = Matrix((1.0, 1.0, 1.0), (4.0, 2.0, 1.0), (16.0, 4.0, 1.0)) val (_Q, _R) = qr(A) val expectedQ = Matrix((-0.06052275326,-0.6022239035,-0.7960297521), (-0.2420910130,-0.7648243574,0.5970223140), (-0.9683640522,0.2288450833,-0.09950371901)) _Q.numRows should be (expectedQ.numRows) _Q.numCols should be (expectedQ.numCols) _Q foreachPair { case ((i,j), v) => v should be (expectedQ(i,j) plusOrMinus 1e-8) } val expectedR = Matrix((-16.52271164,-4.418160988,-1.270977818), (0.,-1.216492285,-1.138203178), (0.,0.,-0.2985111571)) _R.numRows should be (expectedR.numRows) _R.numCols should be (expectedR.numCols) _R foreachPair { case ((i,j), v) => v should be (expectedR(i,j) plusOrMinus 1e-8) } } } ================================================ FILE: src/test/scala/scalala/library/NumericsTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.library import org.scalatest._ import org.scalatest.junit._ import org.scalatest.prop._ import org.scalatest.matchers.ShouldMatchers import org.junit.runner.RunWith import Library._ import Numerics._ import org.scalacheck.{Prop, Arbitrary} @RunWith(classOf[JUnitRunner]) class NumericsTest extends FunSuite with Checkers with ShouldMatchers { test("logSum") { logSum(log(5), log(2)) should be (log(7) plusOrMinus 1e-10) logSum(log(2), log(5)) should be (log(7) plusOrMinus 1e-10) logSum(Double.NegativeInfinity, log(5)) should be (log(5) plusOrMinus 1e-10) logSum(log(5), Double.NegativeInfinity) should be (log(5) plusOrMinus 1e-10) logSum(Double.NegativeInfinity, Double.NegativeInfinity) should be (Double.NegativeInfinity) logSum(log(1), log(2), log(3)) should be (log(6) plusOrMinus 1e-10) logSum(log(1), log(2), Double.NegativeInfinity) should be (log(3) plusOrMinus(1e-10)) val s = Array.tabulate[Double](5)(i => log1p(i)) logSum(s.iterator, s.max) should be (log(15) plusOrMinus 1e-10) logSum(s) should be (log(15) plusOrMinus 1e-10) logSum(Double.NegativeInfinity +: s) should be (log(15) plusOrMinus 1e-10) logSum(s :+ Double.NegativeInfinity) should be (log(15) plusOrMinus 1e-10) } test("logDiff") { logDiff(log(5), log(2)) should be (log(3) plusOrMinus 1e-10) logDiff(log(5), log(5)) should be (Double.NegativeInfinity) evaluating { logDiff(log(5), log(6)) } should produce [IllegalArgumentException] } import Arbitrary._; implicit def ae(x: Double) = new { def =~=(y: Double) = (x-y).abs/x < 1E-6; } // TODO 2.9 filter out Double.MaxValue. /*test("logsumming is approximately associative") { check(Prop.forAll { (a: Double, b:Double, c: Double) => logSum(a,logSum(b,c)) =~= logSum(logSum(a,b),c); }) check(Prop.forAll { (a: Double, b:Double, c: Double) => logSum(a,logSum(b,c)) =~= logSum(a,b,c); }) } test("sum distributes over logsum") { check(Prop.forAll { (a: Double, b:Double, c: Double) => (a + logSum(b,c)) =~= (logSum(a + b,a+c)); }) }*/ } ================================================ FILE: src/test/scala/scalala/library/RandomTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.library import org.scalatest._ import org.scalatest.junit._ import org.scalatest.prop._ import org.junit.runner.RunWith import scalala.library.Random._ import scalala.library.Library._ import scalala.tensor.dense._ @RunWith(classOf[JUnitRunner]) class RandomTest extends FunSuite with Checkers { test("MultivariateGaussian") { // specify rng explicitly so that we don't ever fail this test implicit val mt = new random.MersenneTwisterFast(0l); val Sigma = DenseMatrix((3., 4.), (4., 16.)) val mu = DenseVector(77.,-3.) val X = DenseMatrix.randn(mu, Sigma, 50000)(mt) val (chkSigma, chkMu) = covariance(X, Axis.Horizontal) assert(chkMu forallPairs ( (i,v) => math.abs(v-mu(i)) < 1e-1 ),chkMu) assert(chkSigma forallPairs ( (idx,v) => math.abs(v-Sigma(idx)) < 1e-1 ), chkSigma) } } ================================================ FILE: src/test/scala/scalala/library/StatisticsTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.library import org.scalatest._; import org.scalatest.matchers.ShouldMatchers; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith; import Statistics._ import scalala.tensor.mutable.{Matrix, Vector} @RunWith(classOf[JUnitRunner]) class StatisticsTest extends FunSuite with Checkers with ShouldMatchers { test("corrcoef") { corrcoef(Vector(1,2,3), Vector(2,3,3.4)) should be (0.97072 plusOrMinus 1e-5); assert(corrcoef(Vector[Double](), Vector[Double]()).isNaN); } test("kendall") { val a = Vector(2.5,2.5,2.5,2.5,5,6.5,6.5,10,10,10,10,10,14,14,14,16,17); val b = Vector(1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,2,2); kendall(a,b) should be (0.40754 plusOrMinus 1e-5); val x = Vector(1.5,1.5,3,4,6,6,6,8,9.5,9.5,11,12); val y = Vector(2.5,2.5,7,4.5,1,4.5,6,11.5,11.5,8.5,8.5,10); kendall(x,y) should be (0.55286 plusOrMinus 1e-5); } } ================================================ FILE: src/test/scala/scalala/library/StorageTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.library import org.scalatest._ import org.scalatest.junit._ import org.scalatest.prop._ import org.scalatest.matchers.ShouldMatchers import org.junit.runner.RunWith import scalala.tensor.dense.DenseMatrix import java.io.{ByteArrayInputStream, ByteArrayOutputStream} @RunWith(classOf[JUnitRunner]) class StorageTest extends FunSuite with Checkers with ShouldMatchers { test("StoreTxtAndLoadTxt") { val os = new ByteArrayOutputStream val m = DenseMatrix.randn(5,5) Storage.storetxt(os, m) val n = Storage.loadtxt(new ByteArrayInputStream(os.toByteArray)) m foreachPair ((idx,v) => n(idx) should be (v plusOrMinus 1e-15)) os.reset() Storage.storetxt(os, m) val o = Storage.loadtxt(new ByteArrayInputStream(os.toByteArray), skipRows=2) o.numRows should be (m.numRows-2) o foreachPair ((idx,v) => m(idx._1+2,idx._2) should be (v plusOrMinus 1e-15)) os.reset() Storage.storetxt(os, m) val p = Storage.loadtxt(new ByteArrayInputStream(os.toByteArray), columns=Seq(1,3)) p.numCols should be (2) p foreachPair { case ((row,0), v) => m(row,1) should be (v plusOrMinus 1e-15) case ((row,1), v) => m(row,3) should be (v plusOrMinus 1e-15) case _ => true should be (false) // signal failure } val is = new ByteArrayInputStream("1.0 2.0 #test\n#foo\n3.0 4.0".getBytes) val r = Storage.loadtxt(is) r.numRows should be (2) r.numCols should be (2) r(0,0) should be (1.0) r(0,1) should be (2.0) r(1,0) should be (3.0) r(1,1) should be (4.0) } } ================================================ FILE: src/test/scala/scalala/operators/ArrayTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith import Implicits._; @RunWith(classOf[JUnitRunner]) class ArrayTest extends FunSuite with Checkers { def mk[V:ClassManifest](values : V*) = Array[V](values :_*); test("Negation") { val a = mk(1,2,3); assert((-a).toList === List(-1,-2,-3)); } test("Collection Ops") { val a = mk(1,2,3); val b = mk(4,5,6); assert((a + b).toList === List(5,7,9)); assert((a - b).toList === List(-3,-3,-3)); assert((a :* b).toList === List(4,10,18)); assert((b :/ a).toList === List(4,2,2)); assert((a :/ b.map(_.toDouble)).toList === List(0.25,0.4,0.5)); assert((b :% a).toList === List(0,1,0)); } test("Scalar Ops") { val a = mk(1,2,3); assert((a + 1).toList === List(2.0,3.0,4.0)); assert((a - 1).toList === List(0,1,2)); assert((a * 3.0).toList === List(3.0,6.0,9.0)); assert((a / 2.0).toList === List(0.5,1.0,1.5)); assert((a % 2).toList === List(1,0,1)); } test("Binary Ops") { val a = mk(0,-1,2); val b = mk(0.0,0.0,3.0); assert((a :&& b).toList === List(false,false,true)); assert((a :|| b).toList === List(false,true,true)); assert((a :^^ b).toList === List(false,true,false)); } } ================================================ FILE: src/test/scala/scalala/operators/SparseArrayTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith @RunWith(classOf[JUnitRunner]) class SparseArrayTest extends FunSuite with Checkers { import scalala.collection.sparse.{SparseArray,DefaultArrayValue}; def mk[V:ClassManifest:DefaultArrayValue](values : V*) = SparseArray(values :_*); test("Negation") { val a = mk(1,0,3); assert((-a).toList === List(-1,0,-3)); } test("Zeros") { val a = mk(1,0,3); val b = mk(4,5,0); assert((a :+ b).toList === List(5,5,3)); assert((b :+ a).toList === List(5,5,3)); assert((a :- b).toList === List(-3,-5,3)); assert((a :* b).toList === List(4,0,0)); } test("Collection Ops") { val a = mk(1,2,3); val b = mk(4,5,6); assert((a :+ b).toList === List(5,7,9)); assert((a :- b).toList === List(-3,-3,-3)); assert((a :* b).toList === List(4,10,18)); assert((b :/ a).toList === List(4,2,2)); assert((a :/ b.map(_.toDouble)).toList === List(0.25,0.4,0.5)); assert((b :% a).toList === List(0,1,0)); } test("Scalar Ops") { val a = mk(1,2,3); assert((a :+ 1.0).toList === List(2.0,3.0,4.0)); assert((a :- 1).toList === List(0,1,2)); assert((a :* 3.0).toList === List(3.0,6.0,9.0)); assert((a :/ 2.0).toList === List(0.5,1.0,1.5)); assert((a :% 2).toList === List(1,0,1)); } } ================================================ FILE: src/test/scala/scalala/operators/TupleTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package operators; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith import Implicits._; @RunWith(classOf[JUnitRunner]) class TupleTest extends FunSuite with Checkers { test("Neg") { assert(-(1,2.0,3f) === (-1, -2.0, -3f)); } test("Add") { assert((1,2,3l) + (3.0,2,-1) === (4.0,4,2l)); assert((1,2,3,4) + 1 === (2,3,4,5)); assert(2f :+ (1,2.0,3,4,6) === (3f,4.0,5f,6f,8f)); } test("Sub") { assert((1,2,3l) - (3.0,2,-1) === (-2.0,0,4l)); assert((1,2,3,4) - 1 === (0,1,2,3)); assert(7.0 :- (1,2,3,4) === (6.0,5.0,4.0,3.0)); } test("Mul") { assert((1,2) :* (2,4) === (2,8)); assert((1,2,3,4) :* 2.0 === (2.0,4.0,6.0,8.0)); assert(0.5f :* (1,2,3,4) === (0.5f,1.0f,1.5f,2.0f)); } test("Div") { assert((4,2) :/ (2,2) === (2,1)); assert((1,2,3,4) :/ 2.0 === (0.5,1.0,1.5,2.0)); assert(2f :/ (1,2,4) === (2f,1f,0.5f)); } test("Mod") { assert((3,5) :% 2 === (1,1)); } test("Compare") { assert(((1,2,3) :< (3,2,1)) === (true,false,false)); assert(((1,2,3) :<= (3,2,1)) === (true,true,false)); assert(((1,2,3) :> (3,2,1)) === (false,false,true)); assert(((1,2,3) :>= (3,2,1)) === (false,true,true)); assert(((1,2,3) :== (3,2,1)) === (false,true,false)); assert(((1,2,3) :!= (3,2,1)) === (true,false,true)); } } ================================================ FILE: src/test/scala/scalala/operators/bundles/VectorSpaceTest.scala ================================================ package scalala package operators package bundles /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith import tensor.dense.{DenseVectorCol, DenseVector} // This test basically just makes sure things compile @RunWith(classOf[JUnitRunner]) class VectorSpaceTest extends FunSuite with Checkers { type DVectorSpace[V] = MutableVectorSpace[Double,V]; def vsAdd[V:DVectorSpace](v1: V, v2: V) = { val dv = implicitly[DVectorSpace[V]]; import dv._; v1 + v2; } test("VectorSpace basically works") { VectorSpace.make[DenseVectorCol[Double],Double]; val r = vsAdd(DenseVector(1.,2.,3.),DenseVector(3.,4.,5.)) assert(r === DenseVector(4.,6.,8.)); } } ================================================ FILE: src/test/scala/scalala/scalar/ComplexTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.scalar; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith @RunWith(classOf[JUnitRunner]) class ComplexTest extends FunSuite with Checkers { test("Add") { assert((1 + 2*i) + (2 + 3*i) === (3 + 5*i)); } test("Sub") { assert((1 + 2*i) - (2 + 3*i) === (-1 - i)); } test("Div") { assert((5 + 10*i) / (3 - 4*i) === (-1 + 2*i)); } test("Mul") { assert((1 + 2*i) * (-3 + 6*i) === -15); assert((1 + 5*i) * (-3 + 2*i) === (-13 - 13*i)); } test("Neg") { assert(-(1 + 2*i) === (-1 - 2*i)); } test("Abs/Conj") { assert((3 + 4*i).abs === 5); val c = (1.7 + 2.1*i); assert(c * c.conjugate === 7.3); } test("List[Complex].sum (test ComplexIsFractional)") { val x = List((5 + 7*i), (1 + 3*i), (13 + 17*i)) assert(x.sum === (19 + 27*i)) } test("List[Complex].product (test ComplexIsFractional)") { val x = List((5 + 7*i), (1 + 3*i), (13 + 17*i)) assert(x.product === (-582 + 14*i)) } test("List[Complex].sorted (test ComplexOrdering)") { val x = List((5 + 7*i), (1 + 3*i), (13 + 17*i)) assert(x.sorted === List((1 + 3*i), (5 + 7*i), (13 + 17*i))) } test("Only permit conversion to built-in numeric types when purely real.") { val a = 5 + 0*i // should allow conversion val b = 5 + 5*i // should bork with an IllegalArgumentException def toDouble[Complex](c: Complex)(implicit n: Numeric[Complex]): Double = n.toDouble(c) def toFloat[Complex](c: Complex)(implicit n: Numeric[Complex]): Float = n.toFloat(c) def toInt[Complex](c: Complex)(implicit n: Numeric[Complex]): Int = n.toInt(c) def toLong[Complex](c: Complex)(implicit n: Numeric[Complex]): Long = n.toLong(c) assert(toDouble(a) === 5) assert(toFloat(a) === 5) assert(toInt(a) === 5) assert(toLong(a) === 5) intercept[IllegalArgumentException] { toDouble(b) } intercept[IllegalArgumentException] { toFloat(b) } intercept[IllegalArgumentException] { toInt(b) } intercept[IllegalArgumentException] { toLong(b) } } } ================================================ FILE: src/test/scala/scalala/tensor/CRSTensor2Test.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.tensor; import dense.{DenseVectorCol, DenseVector} import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith import domain._; @RunWith(classOf[JUnitRunner]) class CRSTensor2Test extends FunSuite with Checkers { def typeOf[X](value : X)(implicit m : scala.reflect.Manifest[X]) = m.toString; def show[X](value : X)(implicit m : scala.reflect.Manifest[X]) = { println(typeOf(value) + ":"); println(value); println(); } test("Getting and setting") { val x = mutable.CRSTensor2[String,Int,Double,DenseVectorCol[Double]](DenseVector.zeros(3)); x("a",1) = 3.0; x("b",2) = 7.75; x("c",2) = 8.0; assert(x.valuesIterator.toSet === Set(3.0,8.0,7.75,0.0)); } test("Slice rows") { val x = mutable.CRSTensor2[String,Int,Double,DenseVectorCol[Double]](DenseVector.zeros(3)); x("a",::) := DenseVector(1.,2.,3.) // require expected static type val s1 : DenseVectorCol[Double] = x("a",::); assert(s1 === DenseVector(1.,2.,3.)); // write-through s1(1) = 4; assert(x("a",1) === 4.0); } /* test("Addition") { // require expected static type val x = mutable.CRSTensor2[String,Int,Double,DenseVectorCol[Double]](DenseVector.zeros(3)); x("a") := DenseVector(1.,2.,3.); Counter2(("a","a",1),("b","b",2)) + Counter2(("a","a",3)); assert(v1 === Counter2(("a","a",4),("b","b",2))); // require expected static type val v2 : mutable.Counter2[String,Char,Int] = Counter2(("a",'a',3)) + Counter2(("a",'a',1),("b",'b',2)); assert(v2 === Counter2(("a",'a',4),("b",'b',2))); } test("AddInto") { val x = Counter2[String,String,Int](); x += Counter2(("a","a",1)); assert(x === Counter2(("a","a",1))); x += Counter2(("a","a",2),("a","b",4)); assert(x === Counter2(("a","a",3),("a","b",4))); } test("Subtraction") { assert(mutable.Counter2(("a","a",1),("b","b",2)) - mutable.Counter2(("a","a",3)) === Counter2(("a","a",-2), ("b","b",2))); assert(mutable.Counter2(("a","a",3)) - mutable.Counter2(("a","a",1),("b","b",2)) === Counter2(("a","a",2), ("b","b",-2))); } test("Multiplication") { assert(mutable.Counter2(("a","a",1),("b","b",2)) :* mutable.Counter2(("a","a",3)) === Counter2(("a","a",3))); assert(mutable.Counter2(("a","a",3)) :* mutable.Counter2(("a","a",1),("b","b",2)) === Counter2(("a","a",3))); } */ } ================================================ FILE: src/test/scala/scalala/tensor/Counter2Test.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.tensor; import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith import domain._; @RunWith(classOf[JUnitRunner]) class Counter2Test extends FunSuite with Checkers { def typeOf[X](value : X)(implicit m : scala.reflect.Manifest[X]) = m.toString; def show[X](value : X)(implicit m : scala.reflect.Manifest[X]) = { println(typeOf(value) + ":"); println(value); println(); } test("Getting and setting") { val x = mutable.Counter2[String,Int,Double](); x("a",1) = 3.0; x("b",2) = 7.75; x("c",2) = 8.0; assert(x.valuesIterator.toSet === Set(3.0,8.0,7.75)); } test("Transpose") { val x = mutable.Counter2[String,Int,Double](); x(("a",1),("b",2),("c",2)) := List(3.0,7.75,8.0); assert(x.t.valuesIterator.toSet === Set(3.0,0.0, 0.0, 0.0, 8.0,7.75)); assert(x.t.t === x); assert(x.t.t eq x); x.t(2,"a") = 1; assert(x("a",2) === 1); } test("Slice table") { val x= mutable.Counter2[String,Int,Double](); x(("a",1),("b",2),("c",2)) := List(3.0,7.75,8.0); val table = x(List("a","b","c"),List(1,2)); assert(table.domain === TableDomain(3,2)); table(1,0) = 5; assert(x("b",1) === 5); } test("Slice rows and columns") { val x = mutable.Counter2[String,Int,Double](); x(("a",1),("b",2),("c",2)) := List(3.0,7.75,8.0); // require expected static type val s1 : mutable.Counter[Int,Double] = x("a",::); assert(s1.toMap === Map(1->3.0)); // write-through s1(1) = 4; assert(x("a",1) === 4.0); // require expected static type val s2 : mutable.Counter[String,Double] = x(::,2); assert(s2.toMap === Map("a" -> 0.0, "b" -> 7.75, "c" -> 8.0)); // write-through s2("a") = 1; assert(x("a",2) === 1.0); } test("Addition") { // require expected static type val v1 : mutable.Counter2[String,String,Int] = Counter2(("a","a",1),("b","b",2)) + Counter2(("a","a",3)); assert(v1 === Counter2(("a","a",4),("b","b",2))); // require expected static type val v2 : mutable.Counter2[String,Char,Int] = Counter2(("a",'a',3)) + Counter2(("a",'a',1),("b",'b',2)); assert(v2 === Counter2(("a",'a',4),("b",'b',2))); } test("AddInto") { val x = Counter2[String,String,Int](); x += Counter2(("a","a",1)); assert(x === Counter2(("a","a",1))); x += Counter2(("a","a",2),("a","b",4)); assert(x === Counter2(("a","a",3),("a","b",4))); } test("Subtraction") { assert(mutable.Counter2(("a","a",1),("b","b",2)) - mutable.Counter2(("a","a",3)) === Counter2(("a","a",-2), ("b","b",2))); assert(mutable.Counter2(("a","a",3)) - mutable.Counter2(("a","a",1),("b","b",2)) === Counter2(("a","a",2), ("b","b",-2))); } test("Multiplication") { assert(mutable.Counter2(("a","a",1),("b","b",2)) :* mutable.Counter2(("a","a",3)) === Counter2(("a","a",3))); assert(mutable.Counter2(("a","a",3)) :* mutable.Counter2(("a","a",1),("b","b",2)) === Counter2(("a","a",3))); } test("Shaped Multiplication") { assert(Counter2((0,'a',1),(1,'a',2),(1,'b',3)) * Counter2(('a',0,1),('b',0,2)) === Counter2((0,0,1),(1,0,8))); } } ================================================ FILE: src/test/scala/scalala/tensor/CounterTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.tensor; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith @RunWith(classOf[JUnitRunner]) class CounterTest extends FunSuite with Checkers { val TOLERANCE = 1e-4; def assertClose(a : Double, b : Double) = assert(math.abs(a - b) < TOLERANCE); test("Addition") { assert(mutable.Counter("a"->1,"b"->2) + mutable.Counter("a"->3) === Counter("a"->4,"b"->2)); assert(mutable.Counter("a"->3) + mutable.Counter("a"->1,"b"->2) === Counter("a"->4,"b"->2)); } test("Subtraction") { assert(mutable.Counter("a"->1,"b"->2) - mutable.Counter("a"->3) === Counter("a" -> -2, "b" -> 2)); assert(mutable.Counter("a"->3) - mutable.Counter("a"->1,"b"->2) === Counter("a" -> 2, "b" -> -2)); } test("Multiplication") { assert(mutable.Counter("a"->1,"b"->2) :* mutable.Counter("a"->3) === Counter("a"->3)); assert(mutable.Counter("a"->3) :* mutable.Counter("a"->1,"b"->2) === Counter("a"->3)); } test("MulInner") { val a = mutable.Counter(1->0.56390,2->0.36231,3->0.14601,4->0.60294,5->0.14535); val b = mutable.Counter(1->0.15951,2->0.83671,3->0.56002,4->0.57797,5->0.54450); assertClose(a dot b, .90249); } test("Zero + non zero is nonzero") { val a = mutable.Counter[Int,Double](1->0.0) val b = mutable.Counter(1->0.15951); assert(a + b === b, (a + b).toString + " not equal " + b) } test("Mean") { assert(Counter(0->0,1->1,2->2).mean === 1.0); assert(Counter(0->0.0,1->3.0).mean === 1.5); assert(Counter(0->3l).mean === 3.0); } test("assignment checks both domains") { val a = Counter[Int,Int]() val b = Counter[Int,Int](3->4) a := b assert(a === b) } } ================================================ FILE: src/test/scala/scalala/tensor/DiagonalMatrixTest.scala ================================================ package scalala.tensor /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ import dense.{DenseVector, DenseMatrix} import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith import scalala.library.LinearAlgebra.diag; @RunWith(classOf[JUnitRunner]) class DiagonalMatrixTest extends FunSuite with Checkers { test("Multiply") { val a = DenseMatrix((1, 2, 3),(4, 5, 6),(7,8,9)); val c = diag(DenseVector(6,2,3)); val ac :DenseMatrix[Int] = a * c; // check types; assert(a * c === DenseMatrix( (6,4,9),(24,10,18),(42,16,27))); } } ================================================ FILE: src/test/scala/scalala/tensor/Tensor2Test.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.tensor; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith import domain._; @RunWith(classOf[JUnitRunner]) class Tensor2Test extends FunSuite with Checkers { def mkTensor2() = { val domain = Domain2(SetDomain(Set("a","b","c")), SetDomain(Set(1,2))); mutable.Tensor2[String,Int,Double](domain); } def typeOf[X](value : X)(implicit m : scala.reflect.Manifest[X]) = m.toString; def show[X](value : X)(implicit m : scala.reflect.Manifest[X]) = { println(typeOf(value) + ":"); println(value); println(); } test("Getting and setting") { val x = mkTensor2(); x("a",1) = 3.0; x("b",2) = 7.75; x("c",2) = 8.0; assert(x.valuesIterator.toList === List(3.0,0,0,7.75,0,8.0)); } test("Transpose") { val x = mkTensor2(); x(("a",1),("b",2),("c",2)) := List(3.0,7.75,8.0); assert(x.t.valuesIterator.toList === List(3.0,0,0,0,7.75,8.0)); assert(x.t.t === x); assert(x.t.t eq x); x.t(2,"a") = 1; assert(x("a",2) === 1); } test("Slice table") { val x= mkTensor2(); x(("a",1),("b",2),("c",2)) := List(3.0,7.75,8.0); val table = x(List("a","b","c"),List(1,2)); assert(table.domain === TableDomain(3,2)); table(1,0) = 5; assert(x("b",1) === 5); } test("Slice rows and columns") { val x= mkTensor2(); x(("a",1),("b",2),("c",2)) := List(3.0,7.75,8.0); assert(x("a", ::).isInstanceOf[Tensor1[_,_]]); assert(x("a", ::).toMap === Map(1->3.0, 2->0)) assert(x(::, 2).isInstanceOf[Tensor1[_,_]]); assert(x(::, 2).toMap === Map("a" -> 0.0, "b" -> 7.75, "c" -> 8.0)) } } ================================================ FILE: src/test/scala/scalala/tensor/TensorTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.tensor; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith @RunWith(classOf[JUnitRunner]) class TensorTest extends FunSuite with Checkers { def mkMapTensor() = mutable.Tensor[String,Int](domain.SetDomain(Set("a","b","c"))); test("Get and set values") { val x = mkMapTensor(); assert(x("a") === 0); assert(x("b") === 0); assert(x("c") === 0); x("a") = 5; x("b") = 7; x("c") = 2; assert(x("a") === 5); assert(x("b") === 7); assert(x("c") === 2); } test("Slicing to a sequence") { val x = mkMapTensor(); x("a","b","c") := List(1,2,3); assert(x("a") === 1); assert(x("b") === 2); assert(x("c") === 3); assert(x("c","a","b","b","a").valuesIterator.toList === List(3,1,2,2,1)); } test("Slicing to new keys") { val x = mkMapTensor(); x("a","b","c") := List(1,2,3); val y = x(0->"a", 1->"b", 2->"c"); assert(y(0) === x("a")); assert(y(1) === x("b")); assert(y(2) === x("c")); } test("Map values") { val x = mkMapTensor(); x("a","b","c") := List(1,2,3); assert(x.mapValues(_ % 2 == 0).valuesIterator.toList === List(false,true,false)); } test("Filter values") { val x = mkMapTensor(); x("a","b","c") := List(1,2,3); x(x.findAll(_ >= 2)) := 0; assert(x.valuesIterator.toList === List(1,0,0)); } test("Find") { val x = mkMapTensor(); x("a","b","c") := List(1,2,3); assert(x.findAll(_ >= 2).toList === List("b","c")); } test("Overlapping slice assignments") { val x = mkMapTensor(); x("a","b","c") := List(1,2,3); x("a","b") := x("b","c"); assert(x.valuesIterator.toList === List(2,3,3)); } test("Sorting") { val x = mkMapTensor(); x("a","b","c") := List(5,7,3); assert(x.argsort.toList === List("c","a","b")); assert(x.sorted.valuesIterator.toList === List(3,5,7)); } test("Min/Max") { val x = mkMapTensor(); x("a","b","c") := List(5,7,3); assert(x.min === 3); assert(x.max === 7); assert(x.argmin === "c"); assert(x.argmax === "b"); } } ================================================ FILE: src/test/scala/scalala/tensor/dense/DenseMatrixTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package dense; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith @RunWith(classOf[JUnitRunner]) class DenseMatrixTest extends FunSuite with Checkers { test("Slicing") { val m = DenseMatrix((0,1,2), (3,4,5)); // slice sub-matrix val s1 : mutable.Matrix[Int] = m(0 to 1, 1 to 2); assert(s1 === DenseMatrix((1,2),(4,5))); s1 += 1; assert(m === DenseMatrix((0,2,3),(3,5,6))); // slice row val s2 : DenseVectorRow[Int] = m(0, ::); assert(s2 === DenseVector(0,2,3)); s2 *= 2; assert(m === DenseMatrix((0,4,6),(3,5,6))); // slice column val s3 : DenseVectorCol[Int] = m(::, 1); assert(s3 === DenseVector(4,5)); s3 -= 1; assert(m === DenseMatrix((0,3,6),(3,4,6))); // slice rows val s4 : mutable.Matrix[Int] = m(1 to 1, ::); assert(s4 === DenseMatrix((3,4,6))); // slice columns val s5 : mutable.Matrix[Int] = m(::, 1 to 2); assert(s5 === DenseMatrix((3,6),(4,6))); // slice part of a row val s6a : DenseVectorRow[Int] = m(0, 1 to 2); s6a += 2; val s6b : mutable.VectorRow[Int] = m(0,IndexedSeq(2,1)); s6b -= 1; assert(m === DenseMatrix((0,4,7),(3,4,6))); // slice part of a column val s7a : DenseVectorCol[Int] = m(0 to 1, 0); s7a += 2; val s7b : mutable.VectorCol[Int] = m(IndexedSeq(1,0),0); s7b += 1; assert(m === DenseMatrix((3,4,7),(6,4,6))); } test("Transpose") { val m = DenseMatrix((1,2,3),(4,5,6)); // check that the double transpose gives us back the original assert(m.t.t eq m); // check static type and write-through val t : mutable.Matrix[Int] = m.t; assert(t === DenseMatrix((1,4),(2,5),(3,6))); t(0,1) = 0; assert(m === DenseMatrix((1,2,3),(0,5,6))); } test("Sliced Transpose") { val m = DenseMatrix((0, 1, 2), (3, 4, 5)); // slice sub-matrix val s1: mutable.Matrix[Int] = m(0 to 1, 1 to 2); assert(s1 === DenseMatrix((1, 2), (4, 5))); val t1: mutable.Matrix[Int] = s1.t assert(t1 === DenseMatrix((1, 4), (2, 5))); } test("Min/Max") { val m = DenseMatrix((1,0,0),(2,3,-1)); assert(m.argmin === (1,2)); assert(m.argmax === (1,1)); assert(m.min === -1); assert(m.max === 3); } test("MapValues") { val a : DenseMatrix[Int] = DenseMatrix((1,0,0),(2,3,-1)); val b1 : DenseMatrix[Int] = a.mapValues(_ + 1); assert(b1 === DenseMatrix((2,1,1),(3,4,0))); val b2 : DenseMatrix[Double] = a.mapValues(_ + 1.0); assert(b2 === DenseMatrix((2.0,1.0,1.0),(3.0,4.0,0.0))); } test("Map") { val a : DenseMatrix[Int] = DenseMatrix((1,0,0),(2,3,-1)); val b1 : DenseMatrix[Int] = a.mapTriples((i,j,v) => i + v); assert(b1 === DenseMatrix((1,0,0),(3,4,0))); val b2 : DenseMatrix[Double] = a.mapTriples((i,j,v) => j + v.toDouble); assert(b2 === DenseMatrix((1.0,1.0,2.0),(2.0,4.0,1.0))); } test("Triples") { val a : DenseMatrix[Int] = DenseMatrix((1,0,0),(2,3,-1)); var s = 0; // foreach s = 0; for ((i,j,v) <- a.triples) s += v; assert(s === a.sum); // filter s = 0; for ((i,j,v) <- a.triples; if i % 2 == 0 || j % 2 == 0) s += v; assert(s === 1+2-1); // // map // val b1 : DenseMatrix[Double] = for ((i,j,v) <- a) yield v * 2.0; // assert(b1 === DenseMatrix((2.0,0.0,0.0),(4.0,6.0,-2.0))); // // // map with filter // val b2 : DenseMatrix[Int] = for ((i,j,v) <- a; if j == 0) yield v * 2; // assert(b2 === DenseMatrix((2,0,0),(4,0,0))); } test("horzcat") { val a : DenseMatrix[Int] = DenseMatrix((1,0,0),(2,3,-1)); val result: DenseMatrix[Int] = DenseMatrix((1,0,0,1,0, 0),(2,3,-1,2,3,-1)); assert(DenseMatrix.horzcat(a,a) === result); } test("vertcat") { val a : DenseMatrix[Int] = DenseMatrix((1,0,0),(2,3,-1)); val result: DenseMatrix[Int] = DenseMatrix((1,0,0),(2,3,-1),(1,0,0),(2,3,-1)); assert(DenseMatrix.vertcat(a,a) === result); } test("Multiply") { val a = DenseMatrix((1, 2, 3),(4, 5, 6)); val b = DenseMatrix((7, -2, 8),(-3, -3, 1),(12, 0, 5)); val c = DenseVector(6,2,3); assert(a * b === DenseMatrix((37, -8, 25), (85, -23, 67))); assert(a * c === DenseVector(19,52)); // should be dense val x : DenseMatrix[Int] = a * a.t; assert(x === DenseMatrix((14,32),(32,77))); // should be dense val y : DenseMatrix[Int] = a.t * a; assert(y === DenseMatrix((17,22,27),(22,29,36),(27,36,45))); // should promote val z : DenseMatrix[Double] = b * (b + 1.0); assert(z === DenseMatrix((164,5,107),(-5,10,-27),(161,-7,138))); } test("Trace") { assert(DenseMatrix((1,2,3),(4,5,6)).trace === 1 + 5); assert(DenseMatrix((1,2),(3,4),(5,6)).trace == 1 + 4); assert(DenseMatrix((1,2,3),(4,5,6),(7,8,9)).trace === 1 + 5 + 9); } test("Reshape") { val m : DenseMatrix[Int] = DenseMatrix((1,2,3),(4,5,6)); val r : DenseMatrix[Int] = m.reshape(3,2); assert(m.data eq r.data); assert(r.numRows === 3); assert(r.numCols === 2); assert(r === DenseMatrix((1,5),(4,3),(2,6))); } test("Solve") { // square solve val r1 : DenseMatrix[Double] = DenseMatrix((1.0,3.0),(2.0,0.0)) \ DenseMatrix((1.0,2.0),(3.0,4.0)); assert(r1 === DenseMatrix((1.5, 2.0), (-1.0/6, 0.0))); // matrix-vector solve val r2 : DenseVector[Double] = DenseMatrix((1.0,3.0,4.0),(2.0,0.0,6.0)) \ DenseVector(1.0,3.0); assert(r2 === DenseVector(0.1813186813186811, -0.3131868131868131, 0.43956043956043944)); // wide matrix solve val r3 : DenseMatrix[Double] = DenseMatrix((1.0,3.0,4.0),(2.0,0.0,6.0)) \ DenseMatrix((1.0,2.0),(3.0,4.0)); assert(r3 === DenseMatrix((0.1813186813186811, 0.2197802197802196), (-0.3131868131868131, -0.1978021978021977), (0.43956043956043944, 0.5934065934065933))); // tall matrix solve val r4 : DenseMatrix[Double] = DenseMatrix((1.0,3.0),(2.0,0.0),(4.0,6.0)) \ DenseMatrix((1.0,4.0),(2.0,5.0),(3.0,6.0)); assert(r4 === DenseMatrix((0.9166666666666667, 1.9166666666666672), (-0.08333333333333352, -0.08333333333333436))); } } ================================================ FILE: src/test/scala/scalala/tensor/dense/DenseVectorConstructorTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala.tensor.dense import org.scalatest._ import org.scalatest.matchers.ShouldMatchers import org.scalatest.junit._ import org.junit.runner.RunWith import scalala.tensor.domain.IndexDomain import scalala.library.random.MersenneTwisterFast @RunWith(classOf[JUnitRunner]) class DenseVectorConstructorTest extends FunSuite with ShouldMatchers { test("DenseVectorRow") { val vd: DenseVectorRow[Double] = DenseVectorRow(1.0, 2.0, 3.0) vd.length should equal (3) (vd.values zip (1 to 3)) foreach { case (a,b) => a should equal (b) } val vf: DenseVectorRow[Float] = DenseVectorRow(Array(1.0f, 2.0f, 3.0f)) vf.length should equal (3) (vf.values zip (1 to 3)) foreach { case (a,b) => a should equal (b) } val vdomi: DenseVectorRow[Int] = DenseVectorRow[Int](IndexDomain(10)) vdomi.length should equal (10) vdomi.values foreach (_ should equal (0)) val vdf: DenseVectorRow[Double] = DenseVectorRow.fill(23)(3.0) vdf.length should equal (23) vdf.values foreach (_ should equal (3.0)) val vdz: DenseVectorRow[Double] = DenseVectorRow.zeros[Double](42) vdz.length should equal (42) vdz.values foreach (_ should equal (0)) // TODO: Insert test for zeros and non-primitive types. But -- are there // currently any non-primitive scalars at all? val vbo: DenseVectorRow[Boolean] = DenseVectorRow.ones[Boolean](8) vbo.length should equal (8) vbo.values foreach (_ should equal (true)) val vit: DenseVectorRow[Int] = DenseVectorRow.tabulate[Int](3)(_ * 3) vit.length should equal (3) (vit.values zip (0 to 6 by 3)) foreach { case (a,b) => a should equal (b) } val vir: DenseVectorRow[Int] = DenseVectorRow.range(0, 100, 10) vir.length should equal(10) (vir.values zip (0 to 100 by 10)) foreach { case (a,b) => a should equal (b) } val mt = new MersenneTwisterFast(0l) val vdr: DenseVectorRow[Double] = DenseVectorRow.rand(5, mt) (vdr.values zip Seq(0.548, 0.715, 0.602, 0.544, 0.423)) foreach { case (a,b) => a should be (b plusOrMinus 1e-3) } val vdrn: DenseVectorRow[Double] = DenseVectorRow.randn(5, mt) (vdrn.values zip Seq(1.969, -0.842, -0.505, 1.266, 1.080)) foreach { case (a,b) => a should be (b plusOrMinus 1e-3) } val viri: DenseVectorRow[Int] = DenseVectorRow.randi(1888, 5, mt) (viri.values zip Seq(242, 140, 262, 644, 388)) foreach { case (a,b) => a should equal (b) } val vhc: DenseVectorRow[Double] = DenseVectorRow.horzcat[Double](vd, vd, vd) (vhc.values zip Seq(1,2,3,1,2,3,1,2,3)) foreach { case (a,b) => a should equal (b) } val vvc: DenseMatrix[Int] = DenseVectorRow.vertcat[Int](DenseVectorRow(1,2,3), DenseVectorRow(4,5,6), DenseVectorRow(7,8,9)) vvc foreachPair { case ((i,j), v) => v should equal (i*3+j+1) } evaluating { // Incompatible lengths DenseVectorRow.vertcat(DenseVectorRow(1,2), DenseVectorRow(4,5,6)) } should produce [IllegalArgumentException] } test("DenseVectorCol") { val vd: DenseVectorCol[Double] = DenseVectorCol(1.0, 2.0, 3.0) vd.length should equal (3) (vd.values zip (1 to 3)) foreach { case (a,b) => a should equal (b) } val vf: DenseVectorCol[Float] = DenseVectorCol(Array(1.0f, 2.0f, 3.0f)) vf.length should equal (3) (vf.values zip (1 to 3)) foreach { case (a,b) => a should equal (b) } val vdomi: DenseVectorCol[Int] = DenseVectorCol[Int](IndexDomain(10)) vdomi.length should equal (10) vdomi.values foreach (_ should equal (0)) val vdf: DenseVectorCol[Double] = DenseVectorCol.fill(23)(3.0) vdf.length should equal (23) vdf.values foreach (_ should equal (3.0)) val vdz: DenseVectorCol[Double] = DenseVectorCol.zeros[Double](42) vdz.length should equal (42) vdz.values foreach (_ should equal (0)) // TODO: Insert test for zeros and non-primitive types. But -- are there // currently any non-primitive scalars at all? val vbo: DenseVectorCol[Boolean] = DenseVectorCol.ones[Boolean](8) vbo.length should equal (8) vbo.values foreach (_ should equal (true)) val vit: DenseVectorCol[Int] = DenseVectorCol.tabulate[Int](3)(_ * 3) vit.length should equal (3) (vit.values zip (0 to 6 by 3)) foreach { case (a,b) => a should equal (b) } val vir: DenseVectorCol[Int] = DenseVectorCol.range(0, 100, 10) vir.length should equal(10) (vir.values zip (0 to 100 by 10)) foreach { case (a,b) => a should equal (b) } val mt = new MersenneTwisterFast(0l) val vdr: DenseVectorCol[Double] = DenseVectorCol.rand(5, mt) (vdr.values zip Seq(0.548, 0.715, 0.602, 0.544, 0.423)) foreach { case (a,b) => a should be (b plusOrMinus 1e-3) } val vdrn: DenseVectorCol[Double] = DenseVectorCol.randn(5, mt) (vdrn.values zip Seq(1.969, -0.842, -0.505, 1.266, 1.080)) foreach { case (a,b) => a should be (b plusOrMinus 1e-3) } val viri: DenseVectorCol[Int] = DenseVectorCol.randi(1888, 5, mt) (viri.values zip Seq(242, 140, 262, 644, 388)) foreach { case (a,b) => a should equal (b) } val vhc: DenseVectorCol[Double] = DenseVectorCol.vertcat[Double](vd, vd, vd) (vhc.values zip Seq(1,2,3,1,2,3,1,2,3)) foreach { case (a,b) => a should equal (b) } val vvc: DenseMatrix[Int] = DenseVectorCol.horzcat[Int](DenseVectorCol(1,4,7), DenseVectorCol(2,5,8), DenseVectorCol(3,6,9)) vvc foreachPair { case ((i,j), v) => v should equal (i*3+j+1) } evaluating { // Incompatible lengths DenseVectorCol.horzcat(DenseVectorCol(1,2), DenseVectorCol(4,5,6)) } should produce [IllegalArgumentException] } } ================================================ FILE: src/test/scala/scalala/tensor/dense/DenseVectorTest.scala ================================================ /* * Distributed as part of Scalala, a linear algebra library. * * Copyright (C) 2008- Daniel Ramage * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 USA */ package scalala; package tensor; package dense; import org.scalacheck._ import org.scalatest._; import org.scalatest.junit._; import org.scalatest.prop._; import org.junit.runner.RunWith import mutable.Tensor; @RunWith(classOf[JUnitRunner]) class DenseVectorTest extends FunSuite with Checkers { val TOLERANCE = 1e-4; def assertClose(a : Double, b : Double) = assert(math.abs(a - b) < TOLERANCE); test("Min/Max") { val v = DenseVector(2,0,3,2,-1); assert(v.argmin === 4); assert(v.argmax === 2); assert(v.min === -1); assert(v.max === 3); } test("Mean") { assert(DenseVector(0,1,2).mean === 1.0); assert(DenseVector(0.0,3.0).mean === 1.5); assert(DenseVector(3l).mean === 3.0); } test("Norm") { val v = DenseVector(-0.4326,-1.6656,0.1253,0.2877,-1.1465); assertClose(v.norm(1), 3.6577); assertClose(v.norm(2), 2.0915); assertClose(v.norm(3), 1.8405); assertClose(v.norm(4), 1.7541); assertClose(v.norm(5), 1.7146); assertClose(v.norm(6), 1.6940); assertClose(v.norm(Double.PositiveInfinity), 1.6656); } test("MulInner") { val a = DenseVector(0.56390,0.36231,0.14601,0.60294,0.14535); val b = DenseVector(0.15951,0.83671,0.56002,0.57797,0.54450); assertClose(a dot b, .90249); assertClose(a.t * b, .90249); } test("MulOuter") { val a = DenseVector(1, 2, 3); val b = DenseVector(6, -4, 8); // assert result is a dense matrix val m : DenseMatrix[Int] = a * b.t; assert(m === DenseMatrix((6,-4,8),(12,-8,16),(18,-12,24))); } test("MulMatrix") { val x = DenseVector(1,2).t; val m = DenseMatrix((1,2,1),(2,7,8)); // assert return type is statically a dense row val r : DenseVectorRow[Int] = x * m; assert(r === DenseVector(5, 16, 17)); } test("Slice") { val x = DenseVector.zeros[Int](5); // check that the slice is a vector and mutable val y : mutable.Vector[Int] = x(0 to 2); y :+= 1; val z : mutable.Vector[Int] = x(1 to 3); z :+= 1; assert(x === DenseVector(1,2,2,1,0)); assert(x(0 until 5) === x); assert(try { x(0 to 5); false; } catch { case _ => true }); } test("Slice and Transpose") { val x = DenseVector[Int](1, 2, 3, 4, 5); val s: DenseVectorCol[Int] = x(2 to 3); assert(s === DenseVector(3, 4)); val t: mutable.Vector[Int] = s.t; assert(t === DenseVector(3, 4).t); val emptySlice = x(2 until 2) assert(emptySlice === DenseVector[Int]()) } // https://github.com/scalala/Scalala/pull/19 test("Supertype mutator") { val a = DenseVector(13, 42); val b = DenseVector(7, 42); val expected = DenseVector(6, 0); val direct = a - b; assert(direct === expected); (a: Tensor[Int, Int]) :-= b; assert(a === expected); } test("Transpose") { val x : DenseVectorCol[Int] = DenseVector(1,2,3); // test static type and write-through of transpose val y : DenseVectorRow[Int] = x.t; y(0) = 0; assert(x === DenseVector(0,2,3)); } test("MapValues") { val a : DenseVector[Int] = DenseVector(1,2,3,4,5); val m : DenseVector[Int] = a.mapValues(_ + 1); assert(m === DenseVector(2,3,4,5,6)); } test("ForComprehensions") { val a : DenseVectorCol[Int] = DenseVector(1,2,3,4,5); var s = 0; // foreach s = 0; for (v <- a) s += v; assert(s === a.sum); // filter s = 0; for (v <- a; if v < 3) s += v; assert(s === 1+2); // map val b1 : DenseVectorCol[Double] = for (v <- a) yield v * 2.0; assert(b1 === DenseVector(2.0,4.0,6.0,8.0,10.0)); // map with filter val b2 : DenseVectorCol[Int] = for (v <- a; if v < 3) yield v * 2; assert(b2 === DenseVector(2.0,4.0)); // transpose map with filter val b3 : DenseVectorRow[Int] = for (v <- a.t; if v < 3) yield v * 3; assert(b3 === DenseVector(3,6).t); } test("Tabulate") { val m = DenseVector.tabulate(5)(i => i + 1); assert(m === DenseVector(1,2,3,4,5)); } test("VertCat") { val a1 = DenseVector(1,2,3); val a2 = DenseVector(2,3,4); val res = DenseVector(1,2,3,2,3,4); assert(DenseVector.vertcat(a1,a2) === res); } test("Negation") { val a1 = DenseVector(1,2,3); assert(-a1 == DenseVector(-1,-2,-3)) } } ================================================ FILE: src/test/scala/scalala/tensor/sparse/SparseVectorTest.scala ================================================ package scalala.tensor.sparse import org.scalatest._ import org.scalatest.matchers.ShouldMatchers import org.scalatest.junit._ import org.junit.runner.RunWith import scalala.tensor.dense.DenseVector /** * * @author dlwh */ @RunWith(classOf[JUnitRunner]) class SparseVectorTest extends FunSuite with ShouldMatchers { val TOLERANCE = 1e-4; def assertClose(a : Double, b : Double) = assert(math.abs(a - b) < TOLERANCE, a + " vs. " + b); test("MulInner") { val a = SparseVector(0.56390,0.36231,0.14601,0.60294,0.14535); val b = SparseVector(0.15951,0.83671,0.56002,0.57797,0.54450); val bd = DenseVector(0.15951,0.83671,0.56002,0.57797,0.54450); val bdSplit = DenseVector(0., 0.15951, 0., 0.83671,0., 0.56002, 0., 0.57797, 0., 0.54450); val bdd = bdSplit(1 to 9 by 2) assertClose(a dot b, .90249); assertClose(a dot bd, .90249); assertClose(bd dot a, .90249); assertClose(bdd dot a, .90249); assertClose(a.t * b, .90249); } test("Subtraction") { val a = SparseVector(0.56390,0.36231,0.14601,0.60294,0.14535); val ad = DenseVector(0.56390,0.36231,0.14601,0.60294,0.14535); val b = SparseVector(0.15951,0.83671,0.56002,0.57797,0.54450); val bd = DenseVector(0.15951,0.83671,0.56002,0.57797,0.54450); val bdd = bd - ad b -= a bd -= a assertClose(b.norm(2), bd.norm(2)) assertClose(bdd.norm(2), bd.norm(2)) } }