[jblas] 01/24: Imported Upstream version 0.1
Tony Mancill
tmancill at moszumanska.debian.org
Sun Jan 5 05:45:56 UTC 2014
This is an automated email from the git hooks/post-receive script.
tmancill pushed a commit to branch master
in repository jblas.
commit 23e0f112752c1d0eb18b4f1f86ea15b7c4dec4c4
Author: tony mancill <tmancill at debian.org>
Date: Tue Dec 31 15:19:18 2013 -0800
Imported Upstream version 0.1
---
AUTHORS | 2 +
COPYING | 31 +
INSTALL | 151 +
Makefile | 113 +
README | 53 +
build.xml | 225 ++
config/PrintProperty.java | 7 +
config/config.rb | 139 +
config/configure.rb | 381 +++
config/opts.rb | 87 +
config/path.rb | 55 +
configure | 4 +
fortranwrapper.dump | Bin 0 -> 42859 bytes
javadoc.css | 55 +
nbproject/ide-file-targets.xml | 43 +
nbproject/private/private.xml | 5 +
nbproject/project.xml | 183 ++
scripts/add-license.rb | 137 +
scripts/c-file.c | 48 +
scripts/c-header.h | 51 +
scripts/class_to_float.rb | 87 +
scripts/fortran.rb | 348 +++
scripts/fortran/c.rb | 175 ++
scripts/fortran/java.rb | 586 ++++
scripts/fortranwrapper.rb | 134 +
scripts/java-class.java | 60 +
scripts/java-impl.c | 161 ++
scripts/render-textile.rb | 45 +
scripts/rjpp.rb | 95 +
scripts/static_class_to_float.rb | 109 +
scripts/test_fortranwrapper | 4 +
src/org/jblas/core/ComplexDouble.java | 322 +++
src/org/jblas/core/ComplexFloat.java | 322 +++
src/org/jblas/core/Functions.java | 46 +
src/org/jblas/core/package-info.java | 42 +
src/org/jblas/la/Blas.java | 378 +++
src/org/jblas/la/ComplexDoubleMatrix.java | 2011 +++++++++++++
src/org/jblas/la/ComplexFloatMatrix.java | 2011 +++++++++++++
src/org/jblas/la/DoubleFunction.java | 45 +
src/org/jblas/la/DoubleMatrix.java | 2965 ++++++++++++++++++++
src/org/jblas/la/Eigen.java | 188 ++
src/org/jblas/la/FloatFunction.java | 45 +
src/org/jblas/la/FloatMatrix.java | 2965 ++++++++++++++++++++
src/org/jblas/la/Geometry.java | 181 ++
src/org/jblas/la/JavaBlas.java | 286 ++
src/org/jblas/la/MatrixFunctions.java | 750 +++++
src/org/jblas/la/SimpleBlas.java | 670 +++++
src/org/jblas/la/Solve.java | 101 +
src/org/jblas/la/Trigonometry.java | 67 +
.../la/exceptions/LapackArgumentException.java | 52 +
.../la/exceptions/LapackConvergenceException.java | 53 +
src/org/jblas/la/exceptions/LapackException.java | 53 +
src/org/jblas/la/exceptions/SizeException.java | 43 +
src/org/jblas/la/exceptions/package-info.java | 5 +
src/org/jblas/la/package-info.java | 42 +
src/org/jblas/la/ranges/AllRange.java | 85 +
src/org/jblas/la/ranges/IndicesRange.java | 95 +
src/org/jblas/la/ranges/IntervalRange.java | 86 +
src/org/jblas/la/ranges/PointRange.java | 79 +
src/org/jblas/la/ranges/Range.java | 77 +
src/org/jblas/la/ranges/RangeUtils.java | 86 +
src/org/jblas/la/ranges/package-info.java | 5 +
src/org/jblas/util/LibraryLoader.java | 111 +
src/org/jblas/util/package-info.java | 42 +
src/overview.html | 90 +
src/overview.textile | 80 +
test/org/jblas/core/Dynamic.java | 49 +
test/org/jblas/core/TestComplexFloat.java | 80 +
test/org/jblas/la/BenchmarkAccess.java | 89 +
test/org/jblas/la/BenchmarkComplex.java | 79 +
test/org/jblas/la/BenchmarkElementwise.java | 99 +
test/org/jblas/la/BenchmarkMatrix.java | 164 ++
test/org/jblas/la/ComplexDoubleMatrixTest.java | 88 +
test/org/jblas/la/DemoImages.java | 319 +++
test/org/jblas/la/EigenTest.java | 79 +
test/org/jblas/la/SimpleBlasTest.java | 77 +
test/org/jblas/la/TestBlasDouble.java | 183 ++
test/org/jblas/la/TestBlasDoubleComplex.java | 63 +
test/org/jblas/la/TestBlasFloat.java | 183 ++
test/org/jblas/la/TestDoubleMatrix.java | 641 +++++
test/org/jblas/la/TestFloatMatrix.java | 641 +++++
test/org/jblas/la/TestGeometry.java | 78 +
test/org/jblas/la/TestMatrixFunctions.java | 49 +
test/org/jblas/la/TestSolve.java | 50 +
test/org/jblas/la/TicToc.java | 70 +
85 files changed, 21134 insertions(+)
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..a1a98c6
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Mikio L. Braun - main developer
+Johannes Schaback - additional programming
\ No newline at end of file
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..cab378d
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,31 @@
+Copyright (c) 2009, Mikio L. Braun and contributors
+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 Technische Universität Berlin 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
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..06048d3
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,151 @@
+INSTALL Guide v0.1 - March 30, 2009
+
+jblas depends on a BLAS and LAPACK library for most of its
+computational intensive parts. I recommend getting a high-quality
+implementation like ATLAS http://math-atlas.sourceforge.net/, but
+taking the default implementation should also suffice.
+
+Since the LAPACK libraries which come with ATLAS are incomplete (for
+example, no eigenvalue computations), you also need the Fortran LAPACK
+and BLAS libraries. These will be linked in a way such that the
+optimized ATLAS versions are used when available.
+
+
+STANDARD PROCEDURE
+==================
+
+COMPILING JBLAS
+
+Assuming that you already have LAPACK and ATLAS libraries
+somewhere. This has been tested on Linux (debian lenny) and Windows
+XP/Cygwin.
+
+Prerequisites:
+ - java JDK
+ - ant
+ - ruby
+ - Windows XP: cygwin with gcc, nm, ruby, make, etc.
+
+1. Run "./configure".
+
+2. Running "ant clean all" should do the job ;)
+
+
+INSTALLING JBLAS
+
+1. Add "jblas.jar" to your CLASSPATH
+
+2. By default, the dynamic libraries are extracted from the jar file
+ to the default temporary directory and loaded from there. If you
+ don't want to do this, extract the dynamic library from jblas.jar
+ and copy it somewhere where it can be found.
+
+ For Linux, use LD_LIBRARY_PATH, for Windows, PATH
+
+
+CONFIGURE FLAGS
+
+The configure script understands the following options:
+
+--lapack=DIR
+ Location where the LAPACK and BLAS sources can be found. Location of
+ the extracted lapack-lite files. Otherwise it is assumed that they
+ can be found in the jblas directory
+
+--lapack-build
+ Build only against LAPACK and BLAS, not ATLAS. Note that depending on
+ your configuration, you might still get an ATLAS version (for example, when
+ you compile under debian and ATLAS is installed). Use --static-libs then.
+
+--download-lapack
+ Download and unpack lapack-lite here if not found.
+
+--static-libs
+ Searches for static libraries only. Resulting jblas will not depend on
+ shared LAPACK/BLAS/ATLAS libraries. Default for Windows XP.
+
+--help
+ print this help
+
+
+FURTHER BUILD OPTIONS
+=====================
+
+ADDING OTHER FUNCTIONS FROM LAPACK
+
+Currently, I've only added stubs for LAPACK routines I have needed so
+far. If you want to add further stubs, you need the LAPACK
+sources. Currently, the build is set up to work with the directory
+structure of lapack-lite
+http://www.netlib.org/lapack/lapack-lite-3.1.1.tgz If you want to play
+around with other LAPACK routines, it is best to download the archive
+and unpack it in the jblas directory. You can also type in
+"./configure --download-lapack" to let the configure script handle
+this (requires "wget" and "tar" to be installed)
+
+Then, you have to do a "ant realclean jar" to delete the cached
+information about the Fortran routines and reparse the definitions.
+
+
+ANT TARGETS
+
+javadoc
+ generate javadoc pages
+
+compile-test
+ compiles tests (need junit3)
+
+test
+ run some tests (not that good coverage so far)
+
+compile
+ recompile classes
+
+
+COMPILING LAPACK/BLAS AND ATLAS
+===============================
+
+Here are some hints when you want to compile LAPACK/BLAS and LAPACK
+from scratch. Note that the installation processes for both these
+packages are quite non-standard... .
+
+
+COMPILING LAPACK/BLAS
+
+1. Copy a matching make.inc.* from the INSTALL directory to the base
+ directory, where * stands for your operating system (for example, *
+ = LINUX for Linux and Windows/Cygwin, * = gfortran if you have the
+ (newer) gfortran instead of g77)
+
+2. In make.inc, add the option "-fPIC" to OPTS and NOOPTS
+
+2. Run "make blaslib lapacklib"
+
+4. Rename "blas_*.a" to "libblas_fortran.a" and
+ "lapack_*.a" to "liblapack_fortran.a"
+
+If you want to make a LAPACK build, make sure to specify --static-libs
+when configuring jblas as well.
+
+
+COMPILING ATLAS
+
+A version more recent than 3.8.0 should work
+
+1. Create a build directory with "mkdir build" and cd into it with "cd
+ build".
+
+2. For Linux, run "../configure -Fa alg -fPIC". (Note: for 3.8.3 on my
+ system, I had to add the "-b 32" flag to set the pointer
+ width. Also make sure to turn of any CPU throttling with
+ 'cpufreq-set'.)
+
+ For Windows/Cygwin, run "../configure -O 1", maybe also add "-b 32"
+ for 32bit systems. This basically configures ATLAS as if you
+ compiled on a Linux system, because the Windows/Cygwin option
+ seems to be broken (at least when you're using Cygwin).
+
+3. Run "make" (takes a lot of time, your machine should also not be
+ under load)
+
+4. Only for Linux: Change directory to "build/lib" and run "make shared"
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b0ceaf8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,113 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+# Load the output of the configuration files
+ifneq ($(wildcard configure.out),)
+include configure.out
+else
+$(error Please run "./configure" first...)
+endif
+
+ifneq ($(LAPACK_HOME),)
+LAPACK=$(LAPACK_HOME)/SRC
+BLAS=$(LAPACK_HOME)/BLAS/SRC
+endif
+
+PACKAGE=org.jblas.la
+
+# generate path from package name
+PACKAGE_PATH=$(subst .,/,$(PACKAGE))
+
+#
+# Pattern rules
+#
+# The crazy thing is, with these rules, you ONLY need to specify which
+# object files belong to a source file the rest is determined
+# automatically by make.
+#
+
+# rule to compile files
+%.o : %.c
+ $(CC) $(CFLAGS) $(INCDIRS) -c $< -o $@
+
+# rule to generate shared library from object file
+%.$(SO) : %.o
+ $(LD) $(LDFLAGS) -o $@ $^ $(LOADLIBES)
+
+# the default target
+all : compile-native
+
+compile-native : bin/$(LIB)jblas.$(SO)
+
+generate-wrapper: src/$(PACKAGE_PATH)/Blas.java native/Blas.c
+
+clean:
+ rm -f native/*.o native/*.$(SO) bin/*.$(SO) src/$(PACKAGE_PATH)/Blas.java
+
+ifeq ($(LAPACK_HOME),)
+realclean:
+ @echo "Since you don't have LAPACK sources, I cannot rebuild stubs and deleting the cached information is not a good idea."
+ @echo "(nothing deleted)"
+else
+realclean:
+ rm -f fortranwrapper.dump
+endif
+
+# Generating the stubs. This target requires that the blas sources can be found in ~/src/blas/*.f
+src/$(PACKAGE_PATH)/Blas.java native/Blas.c: scripts/fortranwrapper.rb scripts/fortran.rb scripts/fortran/java.rb scripts/java-class.java scripts/java-impl.c
+ $(RUBY) scripts/fortranwrapper.rb $(PACKAGE) Blas \
+ $(BLAS)/*.f \
+ $(LAPACK)/[sd]gesv.f \
+ $(LAPACK)/[sd]sysv.f \
+ $(LAPACK)/[sd]syev.f \
+ $(LAPACK)/[sd]syev[rdx].f \
+ $(LAPACK)/[sd]posv.f \
+ $(LAPACK)/[sd]geev.f
+
+bin/$(LIB)jblas.$(SO) : native/Blas.$(SO)
+ mv $< $@
+
+#
+# For testing
+#
+VERSION=0.1
+
+make test-dist:
+ ant clean tar
+ rm -rf jblas-$(VERSION)
+ tar xzvf jblas-$(VERSION).tgz
+ cd jblas-$(VERSION)
+ ./configure
+ ant clean jar
+ cd ..
diff --git a/README b/README
new file mode 100644
index 0000000..5f63eb4
--- /dev/null
+++ b/README
@@ -0,0 +1,53 @@
+jblas is a matrix library for Java which uses existing high
+performance BLAS and LAPACK libraries like ATLAS.
+
+Version 0.1, March 28, 2009
+
+INSTALL
+
+In principle, all you need is the jblas.jar in your
+classpath. jblas.jar will then automagically extract your platform
+dependent native library to a tempfile and load it from there. You can
+also put that file somewhere in your load path ($LD_LIBRARY_PATH for
+Linux, %PATH for Windows).
+
+
+BUILDING
+
+If you want to build jBLAS from the sources, you need to set up quite
+a few things:
+
+You will need some implementation of blas and lapack, for example, as
+provided by ATLAS (http://math-atlas.sourceforge.net/). You also need
+the Fortran sources for BLAS and LAPACK, available, for example from
+http://www.netlib.org/lapack/lapack-lite-3.1.1.tgz.
+
+Besides that, you need an installation of ruby, for some code
+generation scripts.
+
+If you still want to build the source your own, see INSTALL for further
+details.
+
+
+HOW TO GET STARTED
+
+Have a look at javadoc/index.html and javadoc/org/jblas/la/DoubleMatrix.html
+
+
+LICENSE
+
+jblas is distributed under a BSD-style license. See the file LICENSE
+for more information.
+
+
+BUGS
+
+If you encounter any bugs, feel free to go to http://jblas.org and
+register a ticket for them. Make sure to include as much information
+as possible. For configuration problems it would also be helpful to
+include the file "configure.log".
+
+
+CONTRIBUTORS
+
+see file AUTHORS
\ No newline at end of file
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..98e5bba
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2009, Mikio L. Braun
+Copyright (c) 2008, Johannes Schaback
+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 Technische Universität Berlin 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
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<project name="java-blas" basedir="." default="jar">
+ <description>
+ This is the build script to compile and deploy the java-blas project.
+ It also generates JavaDoc from source in ../doc.
+ </description>
+
+ <!-- Define directories -->
+ <property name="src" value="${basedir}/src" />
+ <property name="test" value="${basedir}/test" />
+ <property name="bin" value="${basedir}/bin" />
+ <property name="deploy" value="${basedir}/deploy" />
+ <property name="doc" value="${basedir}/javadoc" />
+ <property name="jar" value="${basedir}/jblas.jar" />
+ <property name="include" value="${basedir}/include" />
+ <property name="native" value="${basedir}/native" />
+ <property name="external" value="${basedir}/external" />
+ <property name="scripts" value="${basedir}/scripts" />
+ <property name="pkgbase" value="org.jblas" />
+ <property name="version" value="0.1" />
+ <macrodef name="class-to-float">
+ <attribute name="class"/>
+ <attribute name="path" default="src"/>
+ <sequential>
+ <echo message="Generating float version of @{class}"/>
+ <exec executable="ruby">
+ <arg line="scripts/class_to_float.rb @{path} @{class}"/>
+ </exec>
+ </sequential>
+ </macrodef>
+ <macrodef name="static-class-to-float">
+ <attribute name="class"/>
+ <sequential>
+ <echo message="Add float versions to class @{class}"/>
+ <exec executable="ruby">
+ <arg line="scripts/static_class_to_float.rb src @{class}"/>
+ </exec>
+ </sequential>
+ </macrodef>
+ <macrodef name="rjpp">
+ <attribute name="file"/>
+ <sequential>
+ <exec executable="ruby">
+ <arg line="scripts/rjpp.rb @{file}"/>
+ </exec>
+ </sequential>
+ </macrodef>
+ <target name="clean">
+ <delete dir="${doc}" />
+ <delete dir="${bin}" />
+ <delete dir="${native}" />
+ <delete dir="${include}" />
+ <delete file="${jar}" />
+ <exec executable="make">
+ <arg line="clean" />
+ </exec>
+ </target>
+ <target name="realclean" depends="clean">
+ <exec executable="make">
+ <arg line="realclean" />
+ </exec>
+ </target>
+ <target name="prepare">
+ <mkdir dir="${bin}" />
+ <mkdir dir="${native}" />
+ <mkdir dir="${include}" />
+ </target>
+ <target name="compile" depends="prepare,wrapper,generate-float">
+ <javac destdir="${bin}" source="1.6" debug="on" compiler="javac1.6" fork="yes" nowarn="yes">
+ <src path="${src}" />
+ <classpath>
+ <pathelement location="${external}/junit.jar" />
+ </classpath>
+ </javac>
+ </target>
+ <target name="compile-test" depends="prepare,wrapper,generate-float">
+ <javac destdir="${bin}" source="1.6" debug="on" compiler="javac1.6" fork="yes" nowarn="yes">
+ <src path="${test}" />
+ <classpath>
+ <pathelement location="${external}/junit.jar" />
+ </classpath>
+ </javac>
+ </target>
+ <target name="javah" depends="prepare,wrapper,compile">
+ <javah destdir="${include}" force="yes">
+ <class name="${pkgbase}.la.Blas" />
+ <classpath>
+ <pathelement path="${bin}" />
+ </classpath>
+ </javah>
+ </target>
+ <target name="compile-native" depends="prepare,javah">
+ <exec executable="make">
+ <arg line="compile-native" />
+ </exec>
+ </target>
+ <target name="wrapper">
+ <exec executable="make">
+ <arg line="generate-wrapper" />
+ </exec>
+ </target>
+ <target name="generate-float" depends="preprocess">
+ <class-to-float class="${pkgbase}.la.DoubleMatrix"/>
+ <class-to-float class="${pkgbase}.la.DoubleFunction"/>
+ <class-to-float class="${pkgbase}.core.ComplexDouble"/>
+ <class-to-float path="test" class="${pkgbase}.la.TestDoubleMatrix"/>
+ <class-to-float path="test" class="${pkgbase}.la.TestBlasDouble"/>
+ <class-to-float class="${pkgbase}.la.ComplexDoubleMatrix"/>
+ <static-class-to-float class="${pkgbase}.la.SimpleBlas"/>
+ <static-class-to-float class="${pkgbase}.la.Solve"/>
+ <static-class-to-float class="${pkgbase}.la.Eigen"/>
+ <static-class-to-float class="${pkgbase}.la.Geometry"/>
+ <static-class-to-float class="${pkgbase}.la.MatrixFunctions"/>
+ <static-class-to-float class="${pkgbase}.la.JavaBlas"/>
+ </target>
+ <target name="preprocess">
+ <rjpp file="src/org/jblas/la/DoubleMatrix.java"/>
+ <rjpp file="test/org/jblas/la/TestDoubleMatrix.java"/>
+ <rjpp file="src/org/jblas/la/MatrixFunctions.java"/>
+ <rjpp file="src/org/jblas/la/ComplexDoubleMatrix.java"/>
+ </target>
+ <target name="jar" depends="compile,compile-native">
+ <jar destfile="${jar}">
+ <fileset dir="${bin}">
+ <include name="org/**" />
+ <include name="lib*.so"/>
+ <include name="*.dll"/>
+ </fileset>
+ <manifest>
+ <attribute name="Built-By" value="IDA Group, TU Berlin" />
+ </manifest>
+ </jar>
+ </target>
+ <target name="javadoc" depends="generate-float">
+ <mkdir dir="${doc}" />
+ <javadoc packagenames="org.jblas.*"
+ sourcepath="${src}" defaultexcludes="yes"
+ destdir="${doc}" author="true" version="true"
+ use="true" windowtitle="jblas" linksource="yes"
+ stylesheetfile="javadoc.css" overview="${src}/overview.html">
+ <doctitle>
+ <![CDATA[ <h1>jblas - Linear Algebra for Java</h1> ]]>
+ </doctitle>
+ <bottom>
+ <![CDATA[ written by Mikio L. Braun and Johannes Schaback ]]>
+ </bottom>
+ <tag name="dedication" scope="all" description="Dedication:" />
+ </javadoc>
+ </target>
+ <target name="test" depends="compile-test,jar">
+ <junit printsummary="yes" haltonfailure="yes" showoutput="yes">
+ <classpath>
+ <pathelement location="${external}/junit.jar" />
+ <pathelement path="${bin}" />
+ </classpath>
+ <formatter type="plain" usefile="false" />
+ <test name="${pkgbase}.la.TestBlasDouble" />
+ </junit>
+ </target>
+ <target name="all" depends="jar, javadoc">
+ </target>
+ <target name="debugDirectBufferGC" depends="jar">
+ <java classname="${pkgbase}.la.DebugDirectBufferGC" classpath="${basedir}/jBLAS.jar" />
+ </target>
+ <target name="tar" depends="javadoc">
+ <tar destfile="jblas-${version}.tgz" compression="gzip">
+ <tarfileset dir="${basedir}" prefix="jblas-${version}">
+ <include name="src/**" />
+ <include name="test/**" />
+ <exclude name="**/*.rjpp" />
+ <exclude name="**/semantic.cache" />
+ <include name="scripts/**" />
+ <exclude name="**/*~" />
+ <include name="build.xml" />
+ <include name="Makefile" />
+ <include name="config/*.rb" />
+ <include name="config/*.java" />
+ <include name="fortranwrapper.dump" />
+ <include name="README" />
+ <include name="INSTALL" />
+ <include name="COPYING" />
+ <include name="AUTHORS" />
+ <include name="javadoc.css" />
+ <include name="javadoc/**" />
+ <include name="nbproject/**" />
+ </tarfileset>
+ <tarfileset dir="${basedir}" prefix="jblas-${version}" mode="755"
+ includes="configure" />
+ </tar>
+ </target>
+</project>
diff --git a/config/PrintProperty.java b/config/PrintProperty.java
new file mode 100644
index 0000000..840eaf3
--- /dev/null
+++ b/config/PrintProperty.java
@@ -0,0 +1,7 @@
+public class PrintProperty {
+ public static void main(String[] args) {
+ for (String arg: args) {
+ System.out.println(System.getProperty(arg));
+ }
+ }
+}
\ No newline at end of file
diff --git a/config/config.rb b/config/config.rb
new file mode 100644
index 0000000..618f2bb
--- /dev/null
+++ b/config/config.rb
@@ -0,0 +1,139 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+require 'config/path'
+
+class ConfigError < Exception
+ attr_reader :message
+
+ def initialize(msg)
+ @message = msg
+ end
+end
+
+class Config
+ def initialize
+ @config = Hash.new {|h,k| Array.new }
+ @log = open('configure.log', 'w')
+ end
+
+ def [](k)
+ @config[k]
+ end
+
+ def []=(k, v)
+ @config[k] = v
+ log "Setting #{k} to #{v}"
+ end
+
+ def log(msg)
+ @log.puts(msg)
+ end
+
+ def <<(str)
+ str.each_line do |line|
+ next if line.chomp.empty?
+ i = line.index /\A\s*([a-zA-Z_]+)\s*(\+?=)(.*)/
+ if i.nil?
+ puts "Warning: Cannot parse config definition '#{line}'"
+ next
+ end
+ var = $1
+ op = $2
+ val = $3.strip
+ if op == '='
+ self[var] = val
+ elsif op == '+='
+ if @config.has_key? var
+ self[var] = [self[var], val]
+ else
+ self[var] <<= val
+ end
+ end
+ end
+ return
+ end
+
+ def dump(io)
+ @config.each_pair do |k, v|
+ case v
+ when Array
+ io.puts "#{k}=#{v.join ' '}"
+ else
+ io.puts "#{k}=#{v}"
+ end
+ end
+ end
+
+ def msg(m)
+ print m + "... "
+ $stdout.flush
+ if block_given?
+ msg = yield
+ if msg.nil?
+ ok
+ else
+ puts msg
+ end
+ end
+ end
+
+ def ok
+ puts "ok"
+ end
+
+ def fail(msg=false)
+ puts "*failed*"
+ raise ConfigError, msg
+ end
+
+ def check_cmd(*cmds)
+ cmds.each do |cmd|
+ log "Searching for command #{cmd}"
+ self.fail("coulnd't find command #{cmd}") unless where cmd
+ end
+ yield self if block_given?
+ return
+ end
+
+ def check_files(path, *files)
+ files.each do |file|
+ file = File.join(path, *file)
+ log "Searching for file #{file}"
+ self.fail("couldn't find #{file}") unless File.exist? file
+ end
+ yield self if block_given?
+ return
+ end
+end
diff --git a/config/configure.rb b/config/configure.rb
new file mode 100644
index 0000000..2e9722d
--- /dev/null
+++ b/config/configure.rb
@@ -0,0 +1,381 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+require 'config/path'
+require 'config/config'
+require 'config/opts'
+
+# I shouldn't assume that things have certain layout but instead just try
+# to find the resources:
+#
+# - LAPACK and BLAS sources if I want to recompile (otherwise, not)
+# - lapack_build: complete lapack and blas libraries
+# - atlas_build: complete lapack libraries, atlas libraries
+
+#Todo:
+# - find/download/compile LAPACK
+# - find ATLAS
+# - write out stuff to .config
+# EOS
+
+$opts = Opts.new(ARGV, {}, <<EOS)
+Usage: ./configure [options]
+
+options summary:
+ --lapack=DIR lapack-lite directory
+ --lapack-build build against fortran lapack instead of ATLAS
+ --libpath=DIR1:DIR2:... comma separated list of directories to contain
+ the ATLAS libraries
+ --download-lapack try to download and compile lapack if not
+ found
+ --static-libs look for static libraries only. Results in a
+ dynamically loaded jblas library which does
+ not depend on lapack or atlas libraries.
+ (default for Windows!)
+EOS
+
+config = Config.new
+
+# translate dir (mainly necessary for cygwin)
+def dir(s)
+ case $os_name
+ when 'Linux'
+ s
+ when 'Windows XP'
+ s = s.gsub /\\/, '\\\\\\\\'
+ %x(cygpath -u #{s}).chomp
+ else
+ raise ConfigError, "The OS #{$os_name} is currently unsupported!"
+ end
+end
+
+def libname(name)
+ if $opts.defined? :static_libs
+ 'lib' + name + '.a'
+ else
+ case $os_name
+ when 'Linux'
+ 'lib' + name + '.so'
+ when 'Windows XP'
+ 'lib' + name + '.a'
+ end
+ end
+end
+
+# returns an array of the symbols defined in the library +fn+.
+def libsyms(fn)
+ nmopt = File.extname(fn) == '.so' ? '-D' : ''
+ %x(nm #{nmopt} #{fn}).grep(/ T _?([a-zA-Z0-9_]+)/) {|m| $1}
+end
+
+# indent a multiline text
+class String
+ def indent(cnt)
+ split("\n").map {|l| ' ' * cnt + l}.join("\n")
+ end
+end
+
+begin
+ ######################################################################
+ config.msg('checking for java, javac') do
+ config.check_cmd('java', 'javac')
+ %x(javac config/PrintProperty.java)
+ nil
+ end
+
+ ######################################################################
+ config.msg('checking for nm') do
+ config.check_cmd 'nm'
+ end
+
+ ######################################################################
+ config.msg('determining operating system') do
+ $os_name = %x(java -cp config PrintProperty os.name).chomp
+ if $os_name == 'Windows XP'
+ config.msg 'checking for cygpath' do
+ config.check_cmd 'cygpath'
+ end
+ end
+ $os_name
+ end
+
+ ######################################################################
+ config.msg('locating the Java Development Kit') do
+ $java_home = dir(File.dirname(%x(java -cp config PrintProperty java.home)))
+ p $java_home
+ config.check_files $java_home, ['include', 'jni.h'] do
+ config['JAVA_HOME'] = $java_home
+ end
+ end
+
+ ######################################################################
+ config.msg('deciding whether to use g77 or gfortran') do
+ g77 = where('g77')
+ gfortran = where('gfortran')
+ if g77
+ config['LD'] = 'g77'
+ elsif gfortran
+ config['LD'] = 'gfortran'
+ else
+ config.fail <<EOS.indent 2
+Either g77 or gfortran have to be installed to compile against the
+fortran libraries.
+EOS
+ end
+ end
+
+ ######################################################################
+ config.msg('Setting up gcc and flags') do
+ config.check_cmd('gcc', 'make', 'ld')
+ case $os_name
+ when 'Linux'
+ config << <<EOS
+CC = gcc
+CFLAGS = -fPIC -ggdb
+INCDIRS += -Iinclude -I#{$java_home}/include -I#{$java_home}/include/linux
+SO = so
+LIB = lib
+RUBY=ruby
+LDFLAGS += -shared
+EOS
+ when 'Windows XP'
+ config.check_cmd('cygpath')
+ config << <<EOS
+CC = gcc
+CFLAGS = -ggdb -D__int64='long long'
+INCDIRS += -I"#{dir $java_home}/include" -I"#{dir $java_home}/include/win32" -Iinclude
+LDFLAGS += -mno-cygwin -shared -Wl,--add-stdcall-alias
+SO = dll
+LIB =
+RUBY = ruby
+EOS
+ else
+ config.fail "Sorry, the OS #{$os_name} is currently not supported"
+ end
+ end
+
+ ######################################################################
+ def check_lapack_home(config)
+ config.check_files($lapack_home,
+ ['BLAS', 'SRC', 'dgemm.f'],
+ ['SRC', 'dsyev.f']) do
+ config['LAPACK_HOME'] = $lapack_home
+ end
+ end
+
+ config.msg('locating lapack sources') do
+ $lapack_home = $opts.get :lapack, './lapack-lite-3.1.1'
+ begin
+ check_lapack_home(config)
+ rescue ConfigError => e
+ if $opts.defined? :download_lapack
+ puts "trying to download lapack (about 5M)"
+ File.delete(File.join('.', 'lapack-lite-3.1.1.tgz'))
+ system("wget http://www.netlib.org/lapack/lapack-lite-3.1.1.tgz")
+ system("tar xzvf lapack-lite-3.1.1.tgz")
+ check_lapack_home(config)
+ else
+ puts <<EOS.indent 2
+Couldn\'t locate sources for LAPACK and BLAS. Supply the location
+of the lapack sources with the --lapack=... switch. Sources for lapack can be
+found at http://www.netlib.org/lapack/lapack-lite-3.1.1.tgz or try
+running configure with the --download-lapack option.
+
+Compling jblas should work, but unless you have the LAPACK and BLAS sources
+you cannot add further stubs.
+EOS
+ config['LAPACK_HOME'] = ''
+ $lapack_home = ''
+ end
+ end
+ $lapack_home
+ end
+
+ ######################################################################
+ #
+ # Locating the libraries
+ #
+ # This is a bit involved since the standard ATLAS compilation produces
+ # a liblapack.so which only implements a subset of the lapack functions.
+ # So the basic strategy is to
+ #
+ # (a) find the path to the atlas specific library
+ # (b) find the path to a full lapack library
+ #
+ # Pass the lapack libraries and theirs paths first.
+ #
+ # Of course, if you want to build a lapack-only path, we only search
+ # for the full lapack libraries.
+
+ if $opts.defined? :libpath
+ LIBPATH = $opts[:libpath].split(':')
+ else
+ LIBPATH = %w(/usr/lib /lib /usr/lib/sse2)
+ end
+
+ $libpaths = []
+
+ # Like Set, but retains order in which elements were added
+ def addpath(path)
+ $libpaths << path unless $libpaths.include?
+ end
+
+ def locate_lib(config, name, symbol=nil)
+ p = where(libname(name), LIBPATH) do |fn|
+ symbol.nil? or libsyms(fn).include? symbol
+ end
+
+ if not p
+ config.fail("couldn't find library '#{name}' in\npath #{LIBPATH.join ':'}")
+ end
+
+ config.log "found library #{name} in #{p}"
+ return p
+ end
+
+ # Tries to find one of the libraries +names+ in LIBPATH,
+ # potentially containing the +symbol+.
+ # Returns the path and the actual name of the library
+ def locate_one_of_libs(config, names, symbol=nil)
+ p = nil
+ l = nil
+ config.log "Searching for one of #{names.join ', '} in #{LIBPATH.join ':'}#{if symbol then ' having symbol ' + symbol.to_s end}"
+ for name in names
+ config.log " Searching for #{libname(name)}"
+ p = where(libname(name), LIBPATH) do |fn|
+ symbol.nil? or libsyms(fn).include? symbol
+ end
+
+ if p
+ l = name
+ config.log "Found at #{l} at #{p}"
+ break
+ end
+ end
+
+ if not p
+ config.log "Haven't found any of #{names.join ', '}!"
+ config.fail("couldn't find library '#{name}' in\npath #{LIBPATH.join ':'}")
+ end
+
+ config.log "found library #{l} in #{p}"
+ return p, l
+ end
+
+ ######################################################################
+ config.msg('locating lapack and blas libraries') do
+ begin
+ $lapack_path, $lapack_name =
+ locate_one_of_libs(config, ['lapack_fortran', 'lapack'], 'dsyev_')
+ $blas_path, $blas_name =
+ locate_one_of_libs(config, ['blas_fortran', 'blas', 'f77blas'], 'daxpy_')
+ rescue ConfigError => e
+ config.fail <<EOS.indent 2
+Couldn\'t locate LAPACK and BLAS libraries.
+
+Reason: #{e.message}
+
+You can try to pass the location via --libpath=...
+or build your own LAPACK and BLAS libraries (see INSTALL)
+EOS
+ end
+ $libpaths << $lapack_path
+ $libpaths << $blas_path
+ nil
+ end
+
+ unless $opts.defined? :lapack_build
+ config.msg('locating atlas libraries') do
+ begin
+ $atlas_path = locate_lib(config, 'atlas')
+ $lapack_atlas_path, $lapack_atlas_name =
+ locate_one_of_libs(config, ['lapack_atlas', 'lapack'], 'ATL_dgetri')
+ $cblas_path = locate_lib(config, 'cblas', 'cblas_daxpy')
+ rescue ConfigError => e
+ config.fail <<EOS.indent 2
+Couldn\'t locate ATLAS libraries.
+
+Reason: #{e.message}
+
+You can try to pass the location via --libpath=...
+or build your own ATLAS libraries (see INSTALL)
+EOS
+ end
+ $libpaths << $atlas_path
+ $libpaths << $lapack_atlas_path
+ $libpaths << $cblas_path
+ nil
+ end
+ end
+
+
+ ######################################################################
+ # Some sanity checks, in particular that ATLAS's and LAPACK's lapack
+ # library doesn't have the same name... .
+ if $lapack_name == $lapack_atlas_name
+ config.fail <<EOS.indent 2
+The full lapack library and the one from ATLAS have the same name which
+makes it impossible to link in both. Either fiddle with --libpath=... or
+try renaming some of the libraries:
+
+lapack's #{libname $lapack_name} to #{libname 'lapack_fortran'}
+ATLAS' #{libname $lapack_name} to #{libname 'lapack_atlas'}
+EOS
+ end
+
+ # Okay, then we're done!
+ if $opts.defined? :lapack_build
+ config << <<EOS
+LDFLAGS += #{$libpaths.map {|s| '-L' + s}.join ' '}
+LOADLIBES = -l#{$lapack_name} -l#{$blas_name}
+EOS
+ else
+ config << <<EOS
+LDFLAGS += #{$libpaths.map {|s| '-L' + s}.join ' '}
+LOADLIBES = -l#{$lapack_atlas_name} -l#{$lapack_name} -l#{$blas_name} -lcblas -latlas
+EOS
+ end
+
+ ######################################################################
+ # dumping results
+ puts
+ puts 'Configuration succesfull, writing out results to configure.out'
+ open('configure.out', 'w') {|f| config.dump f}
+
+rescue ConfigError => e
+ puts
+ puts "Configuration failed!"
+ puts
+ puts "Reason: #{e.message}"
+end
diff --git a/config/opts.rb b/config/opts.rb
new file mode 100644
index 0000000..b1f7b29
--- /dev/null
+++ b/config/opts.rb
@@ -0,0 +1,87 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+class Opts
+ attr_accessor :opts, :args
+
+ def initialize(args, shortcuts={}, usage=nil)
+ @opts = Hash.new
+ @args = Array.new
+ args.each do |a|
+ case a
+ when '-h'
+ puts usage
+ exit
+ when '--help'
+ puts usage
+ exit
+ when /\A--/
+ a = a[2..-1]
+ if a.index('=')
+ key, value = a.split('=')
+ opts[key.gsub(/-/, '_').to_sym] = value
+ else
+ opts[a.gsub(/-/, '_').to_sym] = true
+ end
+ when /\A-/
+ key = a[1..1].to_sym
+ key = shortcuts[key] if shortcuts.has_key? key
+ value = a[2..-1]
+ if not value.empty?
+ opts[key] = value
+ else
+ opts[key] = true
+ end
+ else
+ @args << a
+ end
+ end
+
+ def defined?(v)
+ @opts.has_key? v
+ end
+
+ def [](key)
+ @opts[key]
+ end
+
+ def get(key, default)
+ if @opts.include? key
+ @opts[key]
+ else
+ default
+ end
+ end
+ end
+end
diff --git a/config/path.rb b/config/path.rb
new file mode 100644
index 0000000..85b0b3f
--- /dev/null
+++ b/config/path.rb
@@ -0,0 +1,55 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+require 'set'
+
+PATH = ENV['PATH'].split(':')
+
+def where(file, path=PATH)
+ path.each do |p|
+ fn = File.join(p, file)
+ #print " Checking #{fn}"
+ if File.exist? fn
+ #puts " found"
+ if block_given?
+ return p if yield fn
+ else
+ return p
+ end
+ else
+ #puts
+ end
+ end
+ return
+end
diff --git a/configure b/configure
new file mode 100755
index 0000000..86c95a9
--- /dev/null
+++ b/configure
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+ruby config/configure.rb $*
+
diff --git a/fortranwrapper.dump b/fortranwrapper.dump
new file mode 100644
index 0000000..98e79c2
Binary files /dev/null and b/fortranwrapper.dump differ
diff --git a/javadoc.css b/javadoc.css
new file mode 100644
index 0000000..ec5066d
--- /dev/null
+++ b/javadoc.css
@@ -0,0 +1,55 @@
+/* Javadoc style sheet */
+
+/* Define colors, fonts and other style attributes here to override the defaults */
+
+/* Page background color */
+body { background-color: #FFFFFF; color:#000000 }
+
+/* Headings */
+h1 { font-size: 145% }
+
+/* Table colors */
+.TableHeadingColor { background: #CCCCFF; color:#000000 } /* Dark mauve */
+.TableSubHeadingColor { background: #EEEEFF; color:#000000 } /* Light mauve */
+.TableRowColor { background: #FFFFFF; color:#000000 } /* White */
+
+/* Font used in left-hand frame lists */
+.FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+.FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+.FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+
+/* Navigation bar fonts and colors */
+.NavBarCell1 { background-color:#EEEEFF; color:#000000} /* Light mauve */
+.NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* Dark Blue */
+.NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;}
+.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;}
+
+.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000}
+.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000}
+
+table.my {
+ border-collapse: collapse;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.my td, th {
+ border: solid 1px #888;
+ padding: 5px;
+}
+
+table.my th {
+ background-color: #eef;
+}
+
+span.code {
+ display:block;
+ padding: 0;
+ padding: 1em;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 0;
+ margin-right: 0;
+ font-family: monospace;
+ text-align: center;
+}
\ No newline at end of file
diff --git a/nbproject/ide-file-targets.xml b/nbproject/ide-file-targets.xml
new file mode 100644
index 0000000..0dcdfda
--- /dev/null
+++ b/nbproject/ide-file-targets.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir=".." name="jBLAS-IDE">
+ <import file="../build.xml"/>
+ <!-- TODO: edit the following target according to your needs -->
+ <!-- (more info: http://www.netbeans.org/kb/41/freeform-config.html#runsingle) -->
+ <target name="test-selected-file-in-test-old">
+ <fail unless="run.class">Must set property 'run.class'</fail>
+ <junit classname="${run.class}" failonerror="true" fork="true">
+ <classpath>
+ <pathelement path="external/junit.jar:bin"/>
+ </classpath>
+ </junit>
+ </target>
+ <target depends="compile,compileNative" name="test-selected-file-in-test">
+ <mkdir dir="test-results"/>
+ <junit errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
+ <test name="${run.class}" todir="test-results"/>
+ <classpath path="${bin}:external/junit.jar"/>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ </junit>
+ </target>
+ <!-- TODO: edit the following target according to your needs -->
+ <!-- (more info: http://www.netbeans.org/kb/41/freeform-config.html#runsingle) -->
+ <target name="debug-test-selected-file-in-test">
+ <fail unless="debug.class">Must set property 'debug.class'</fail>
+ <path id="cp">
+ <pathelement path="${bin}:external/junit.jar"/>
+ </path>
+ <nbjpdastart addressproperty="jpda.address" name="jBLAS" transport="dt_socket">
+ <classpath refid="cp"/>
+ </nbjpdastart>
+ <junit errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
+ <classpath path="${classes.dir}:external/junit.jar:${test.classes.dir}"/>
+ <jvmarg value="-Xdebug"/>
+ <jvmarg value="-Xnoagent"/>
+ <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
+ <test name="${debug.class}" todir="${test.results.dir}"/>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ </junit>
+ </target>
+</project>
diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml
new file mode 100644
index 0000000..2dd4812
--- /dev/null
+++ b/nbproject/private/private.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
+ <data xmlns="http://www.netbeans.org/ns/profiler/1" profile-file-target="" profile-target="debugDirectBufferGC" version="0.4"/>
+ <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
+</project-private>
diff --git a/nbproject/project.xml b/nbproject/project.xml
new file mode 100644
index 0000000..33deba3
--- /dev/null
+++ b/nbproject/project.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.ant.freeform</type>
+ <configuration>
+ <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1">
+ <name>jBLAS-Array</name>
+ </general-data>
+ <general-data xmlns="http://www.netbeans.org/ns/freeform-project/2">
+ <!-- Do not use Project Properties customizer when editing this file manually. -->
+ <name>jBLAS-Array</name>
+ <properties/>
+ <folders>
+ <source-folder>
+ <label>jBLAS</label>
+ <location>.</location>
+ <encoding>UTF-8</encoding>
+ </source-folder>
+ <source-folder>
+ <label>src</label>
+ <type>java</type>
+ <location>src</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ <encoding>UTF-8</encoding>
+ </source-folder>
+ <source-folder>
+ <label>test</label>
+ <type>java</type>
+ <location>test</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ <encoding>UTF-8</encoding>
+ </source-folder>
+ <source-folder>
+ <label>scripts</label>
+ <type>java</type>
+ <location>scripts</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ <encoding>UTF-8</encoding>
+ </source-folder>
+ <source-folder>
+ <label>native</label>
+ <type>java</type>
+ <location>native</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ <encoding>UTF-8</encoding>
+ </source-folder>
+ <source-folder>
+ <label>include</label>
+ <type>java</type>
+ <location>include</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ <encoding>UTF-8</encoding>
+ </source-folder>
+ </folders>
+ <ide-actions>
+ <action name="build">
+ <target>jar</target>
+ </action>
+ <action name="clean">
+ <target>clean</target>
+ </action>
+ <action name="javadoc">
+ <target>javadoc</target>
+ </action>
+ <action name="test">
+ <target>test</target>
+ </action>
+ <action name="rebuild">
+ <target>clean</target>
+ <target>jar</target>
+ </action>
+ <action name="test.single">
+ <script>nbproject/ide-file-targets.xml</script>
+ <target>test-selected-file-in-test</target>
+ <context>
+ <property>run.class</property>
+ <folder>test</folder>
+ <pattern>\.java$</pattern>
+ <format>java-name</format>
+ <arity>
+ <one-file-only/>
+ </arity>
+ </context>
+ </action>
+ <action name="debug.single">
+ <script>nbproject/ide-file-targets.xml</script>
+ <target>debug-selected-file-in-test</target>
+ <context>
+ <property>debug.class</property>
+ <folder>test</folder>
+ <pattern>\.java$</pattern>
+ <format>java-name</format>
+ <arity>
+ <one-file-only/>
+ </arity>
+ </context>
+ </action>
+ <action name="debug.test.single">
+ <script>nbproject/ide-file-targets.xml</script>
+ <target>debug-test-selected-file-in-test</target>
+ <context>
+ <property>debug.class</property>
+ <folder>test</folder>
+ <pattern>\.java$</pattern>
+ <format>java-name</format>
+ <arity>
+ <one-file-only/>
+ </arity>
+ </context>
+ </action>
+ </ide-actions>
+ <export>
+ <type>jar</type>
+ <location>jBLAS.jar</location>
+ <build-target>jar</build-target>
+ </export>
+ <view>
+ <items>
+ <source-folder style="packages">
+ <label>src</label>
+ <location>src</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ </source-folder>
+ <source-folder style="packages">
+ <label>test</label>
+ <location>test</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ </source-folder>
+ <source-folder style="packages">
+ <label>scripts</label>
+ <location>scripts</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ </source-folder>
+ <source-folder style="packages">
+ <label>native</label>
+ <location>native</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ </source-folder>
+ <source-folder style="packages">
+ <label>include</label>
+ <location>include</location>
+ <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+ </source-folder>
+ <source-file>
+ <location>build.xml</location>
+ </source-file>
+ </items>
+ <context-menu>
+ <ide-action name="build"/>
+ <ide-action name="rebuild"/>
+ <ide-action name="clean"/>
+ <ide-action name="javadoc"/>
+ <ide-action name="test"/>
+ </context-menu>
+ </view>
+ <subprojects/>
+ </general-data>
+ <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/2">
+ <compilation-unit>
+ <package-root>src</package-root>
+ <built-to>jBLAS.jar</built-to>
+ <source-level>1.5</source-level>
+ </compilation-unit>
+ <compilation-unit>
+ <package-root>test</package-root>
+ <unit-tests/>
+ <classpath mode="compile">src:../../../../usr/share/java/junit.jar</classpath>
+ <source-level>1.5</source-level>
+ </compilation-unit>
+ <compilation-unit>
+ <package-root>scripts</package-root>
+ <source-level>1.5</source-level>
+ </compilation-unit>
+ <compilation-unit>
+ <package-root>native</package-root>
+ <source-level>1.5</source-level>
+ </compilation-unit>
+ <compilation-unit>
+ <package-root>include</package-root>
+ <source-level>1.5</source-level>
+ </compilation-unit>
+ </java-data>
+ </configuration>
+</project>
diff --git a/scripts/add-license.rb b/scripts/add-license.rb
new file mode 100644
index 0000000..ef176ee
--- /dev/null
+++ b/scripts/add-license.rb
@@ -0,0 +1,137 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+LICENSE = <<EOS.split("\n")
+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 Technische Universität Berlin 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
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+EOS
+
+DEFAULT_COPYRIGHT = "2009, Mikio L. Braun"
+
+BLB = '--- BEGIN LICENSE BLOCK ---'
+ELB = "--- END LICENSE BLOCK ---"
+
+SUFFIXMAP = {
+ '.rb' => :hash,
+ '.c' => :doubleslash,
+ '.h' => :doubleslash,
+ '.java' => :java
+}
+SUFFIXMAP.default = :hash
+
+# Comment a piece of text (given as an array of lines) for
+# a given code type
+def comment_block(file, txt)
+ #puts File.extname(file)
+ code = SUFFIXMAP[File.extname(file)]
+ case code
+ when :hash
+ ['## ' + BLB] + txt.map {|l| '# ' + l} + ['## ' + ELB]
+ when :java
+ ['// ' + BLB, '/* '] + txt.map{|l| ' * ' + l} + [' */', '// ' + ELB, ]
+ when :doubleslash
+ ['/// ' + BLB] + txt.map {|l| '// ' + l} + ['/// ' + ELB]
+ else
+ LICENSE
+ end
+end
+
+# Remove the license block and return the found copyrights or
+# DEFAULT_COPYRIGHT
+def remove_license_block(code)
+ copyrights = []
+ if code[0] =~ Regexp.new(BLB)
+ code.shift
+ while not code.empty? and code[0] !~ Regexp.new(ELB)
+ if code[0] =~ /Copyright \(c\) (.+)/
+ copyrights << $1
+ end
+ code.shift
+ end
+ code.shift
+ code.shift
+ end
+ #return [DEFAULT_COPYRIGHT]
+ return copyrights.empty? ? [DEFAULT_COPYRIGHT] : copyrights
+end
+
+# Add a license to a file
+def add_license(file)
+ #puts "--- #{file}"
+ code = open(file).read
+ open(file + '~', 'w') {|f| f.print code}
+ code = code.split("\n")
+ copyrights = remove_license_block(code)
+ license_block = copyrights.map {|cr| 'Copyright (c) ' + cr} + LICENSE
+ license_block = comment_block(file,license_block)
+ code = license_block + [''] + code
+ open(file, 'w') {|f| f.puts code.join("\n")}
+end
+
+FILES = ['{src,test}/**/*.java',
+ 'scripts/*.{c,h,java}',
+ '{scripts,config}/**/*.rb',
+ 'include/*.h', 'Makefile']
+#FILES = 'Makefile.lb'
+files = FILES.map {|p| Dir.glob(p)}.flatten
+
+files.each do |file| add_license file end
diff --git a/scripts/c-file.c b/scripts/c-file.c
new file mode 100644
index 0000000..de84b51
--- /dev/null
+++ b/scripts/c-file.c
@@ -0,0 +1,48 @@
+/// --- BEGIN LICENSE BLOCK ---
+// Copyright (c) 2009, Mikio L. Braun
+// 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 Technische Universität Berlin 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
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/// --- END LICENSE BLOCK ---
+
+/*
+ * Wrapper files for LAPACK
+ *
+ *
+ * automatically generated by fortranwrapper
+ */
+
+#include "<%= filename %>.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+<% for r in routines %>
+<%= C.wrapper_for r -%>
+<% end%>
diff --git a/scripts/c-header.h b/scripts/c-header.h
new file mode 100644
index 0000000..9f7c3c7
--- /dev/null
+++ b/scripts/c-header.h
@@ -0,0 +1,51 @@
+/// --- BEGIN LICENSE BLOCK ---
+// Copyright (c) 2009, Mikio L. Braun
+// 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 Technische Universität Berlin 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
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/// --- END LICENSE BLOCK ---
+
+/*
+ * Wrapper files for FORTRAN
+ *
+ * automatically generated by fortranwrapper
+ */
+
+#ifndef <%= filename.upcase %>_H
+#define <%= filename.upcase %>_H
+
+typedef struct { float r; float i; } <%= C::COMPLEX_TYPE %>;
+typedef struct { double r; double i; } <%= C::DOUBLE_COMPLEX_TYPE %>;
+
+<% routines.each do |r| -%>
+extern <%= C.declaration_for r %>;
+<% end -%>
+
+#endif
diff --git a/scripts/class_to_float.rb b/scripts/class_to_float.rb
new file mode 100644
index 0000000..43ce5bd
--- /dev/null
+++ b/scripts/class_to_float.rb
@@ -0,0 +1,87 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+def readfile(fn)
+ f = open(fn)
+ s = f.read
+ f.close
+ s
+end
+
+def writefile(fn, s)
+ f = open(fn, 'w')
+ f.write s
+ f.close
+end
+
+def classfile(classname)
+ classname.tr('.', File::SEPARATOR) + '.java'
+end
+
+def translate(s)
+ s.gsub! /DoubleMatrix/, 'FloatMatrix'
+ s.gsub! /DoubleBuffer/, 'FloatBuffer'
+ s.gsub! /DoubleVector/, 'FloatVector'
+ s.gsub! /ComplexDouble/, 'ComplexFloat'
+ s.gsub! /([0-9]+\.[0-9]+)/, '\1f'
+ s.gsub! /double/, 'float'
+ s.gsub! /(\s)Blas\.dz/, '\1Blas.sc'
+ s.gsub! /(\s)Blas\.d/, '\1Blas.s'
+ s.gsub! /(\s)Blas\.z/, '\1Blas.c'
+ s.gsub! /nextDouble/, 'nextFloat'
+ s.gsub! /DoubleFunction/, 'FloatFunction'
+ s.gsub! /TestBlasDouble/, 'TestBlasFloat'
+ s.gsub! /Double\./, 'Float.'
+ s.gsub! /readDouble/, 'readFloat'
+ s
+end
+
+if ARGV.size < 2
+ puts "Usage: ruby class_to_float.rb srcprefix classname"
+ exit
+end
+
+prefix = ARGV[0]
+source = ARGV[1]
+target = source.gsub(/Double/, 'Float')
+
+sourcefn = File.join(prefix, classfile(source))
+targetfn = File.join(prefix, classfile(target))
+
+if File.exist? sourcefn
+ s = readfile(sourcefn)
+ writefile(targetfn, translate(s))
+else
+ puts "Could not read file #{sourcefn}"
+end
diff --git a/scripts/fortran.rb b/scripts/fortran.rb
new file mode 100644
index 0000000..eef9028
--- /dev/null
+++ b/scripts/fortran.rb
@@ -0,0 +1,348 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+# This module contains a minimum of parsing routines and data types to
+# be able to write automatic wrappers of blas and lapack routines
+module Fortran
+
+ # Fortran 70 types
+ # Source: http://www.nacs.uci.edu/dcslib/sun/compilers/fortran/f77rm/2_data.doc.html
+ Types = ['BYTE',
+ 'CHARACTER',
+ 'CHARACTER\*[0-9]+',
+ 'CHARACTER\*\(\s*\*\s*\)',
+ 'COMPLEX(?:\*(?:8|16))?',
+ 'DOUBLE\ COMPLEX',
+ 'DOUBLE\ PRECISION',
+ 'INTEGER(?:\*(?:2|4|8))?',
+ 'LOGICAL(?:\*(?:1|2|4|8))?',
+ 'REAL(?:\*(?:4|8))?']
+
+ # Mapping of some types to default names
+ DefaultTypes = {
+ 'BYTE' => 'LOGICAL*1',
+ 'COMPLEX' => 'COMPLEX*8',
+ 'DOUBLE COMPLEX' => 'COMPLEX*16',
+ 'DOUBLE PRECISION' => 'REAL*8',
+ 'INTEGER' => 'INTEGER*4',
+ 'LOGICAL' => 'LOGICAL*4',
+ 'REAL' => 'REAL*4' }
+
+
+ # Return a regular expression which matches against all Fortran::Types.
+ def self.types_as_regexp
+ Fortran::Types.join('|')
+ end
+
+ # Return a Fortran subroutine object.
+ # +args+ is an array of the names of the arguments
+ def self.subroutine(name, args)
+ Routine.new FortranType.new('VOID'), name, args
+ end
+
+ # Return a Fortran function object.
+ def self.function(return_type, name, args)
+ Routine.new FortranType.new(return_type), name, args
+ end
+
+ # Concatenate all continuated lines. These are lines where there is a
+ # mark ('$' or 'C') in the 5th column. For example:
+ #
+ # 1234567890
+ # SUBROUTINE DGEEVX( BALANC, JOBVL, JOBVR, SENSE, N, A, LDA, WR, WI,
+ # $ VL, LDVL, VR, LDVR, ILO, IHI, SCALE, ABNRM,
+ # $ RCONDE, RCONDV, WORK, LWORK, IWORK, INFO )
+ #
+ # Returns an array of the resulting lines.
+ def self.parse_continuations(lines)
+ m = []
+ lines.each do |l|
+ l.chomp!
+ if l =~ /^ [$C]\ *( .+)/ then
+ m[-1] << $1
+ else
+ m << l
+ end
+ end
+ m
+ end
+
+ # Map fortran types to a unique name (via DefaultTypes).
+ def self.standardize_type(name)
+ name.strip!
+ DefaultTypes.fetch name, name
+ end
+
+
+ # Represents a FORTRAN data type
+ class FortranType
+ attr_accessor :basetype, :array, :comment
+
+ # Construct new FortranType. Set array and comment later if you want to.
+ def initialize(type, array=false, comment=nil)
+ @basetype = Fortran.standardize_type type
+ @array = array
+ @comment = comment
+ end
+
+ def to_s # :nodoc:
+ s = @basetype.clone
+ s << ' (array)' if @array
+ s << ' # ' + @comment if comment
+ s
+ end
+ end
+
+ # This class describes a fortran subroutine or function. It
+ # mainly collects all the information about the arguments and
+ # their types.
+ #
+ # You can use Fortran.subroutine and Fortran.function to
+ # construct the respective type.
+ class Routine
+ # name of the routine
+ attr_reader :name
+ # argument names of the routines (as array)
+ attr_reader :args
+ # hash mapping argument names to FortranType objects
+ attr_reader :argtype
+ # return type as FortranType object or nil
+ attr_reader :return_type
+
+ # Construct a new Routine object. If return_type is nil, it is a subroutine.
+ def initialize(return_type, name, args)
+ @return_type = return_type
+ @name = name
+ @args = args
+ @argtype = Hash.new
+ end
+
+ # Check whether all arguments have at least types.
+ def have_all_types?
+ @args.each do |a|
+ unless @argtype.has_key? a
+ return false
+ end
+ end
+ true
+ end
+
+ def each_arg
+ args.each do |name|
+ type = argtype[name]
+ yield name, type
+ end
+ end
+
+ def to_s # :nodoc:
+ s = [ (@return_type ? "#@return_type function " : "subroutine ") + @name + "\n"]
+ @args.each do |arg|
+ s << " #{arg} of type #{@argtype[arg]}\n"
+ end
+ unless workspace_arguments.empty?
+ s << "Workspace Arguments: " + workspace_arguments.join(', ')
+ end
+ s.join
+ end
+
+ def number_of_scalar_output_arguments
+ count = 0
+ each_arg do |name, type|
+ if type.comment =~ /output/ and not type.array
+ count += 1
+ end
+ end
+ count
+ end
+
+ # Generate some code for each argument and collect the results
+ def gen_each_arg(joinwith="\n")
+ s = []
+ args.each do |name|
+ t = yield name, argtype[name]
+ s << t unless t.nil?
+ end
+ return s.join(joinwith)
+ end
+
+ def workspace_arguments
+ results = []
+ args.each_with_index do |a, i|
+ results << a if workspace_argument? a
+ end
+ return results
+ end
+
+ def workspace_argument?(name)
+ i = args.index(name)
+ name =~ /WORK\Z/ and i < @args.size - 1 and args[i+1] == 'L' + name
+ end
+
+ def workspace_size_argument?(name)
+ i = args.index(name)
+ name =~ /\AL[A-Z]*WORK\Z/ and i > 0 and args[i-1] == name[1..-1]
+ end
+ end
+
+ # In order to pass additional information to the template code,
+ # subclass Template Context and put the information into instance
+ # variables. These will then be accessible from the template.
+ class TemplateContext
+
+ # Generate output from a template file.
+ # This function also uses the new-line suppressing extension as
+ # in rails. Put a minus after or before the '%' to suppress the
+ # previous or following newline.
+ #
+ # <%= some expression %>\nblahblah <- newline is output
+ # <%= some expression -%>\nblahblah <- newline is removed
+ def generate(template_file)
+ f = open(template_file)
+ template = f.read
+ f.close
+
+ # Add the littel newline suppression hack as in rails.
+ # Minus in front of closing or after opening '%' suppresses newlines.
+ template.gsub! /-%>\n/, '%>'
+ template.gsub! /\n<%-/, '<%'
+
+ ERB.new(template).result(binding)
+ end
+ end
+
+ #
+ # Regular expressions used below.
+ #
+ # Stored here for better performance
+ #
+
+ # Matches e.g. SUBROUTINE DAXPY(N,DA,DX,INCX,DY, INCY)
+ SubroutineDecl =
+ Regexp.compile /SUBROUTINE ([A-Z0-9]+)\(\ *([A-Z0-9, ]+)\ *\)/
+
+ # Matches e.g. DOUBLE PRECISION FUNCTION DDOT(N,DX,INCX,DY,INCY)
+ FunctionDecl =
+ Regexp.compile /\ +([A-Z ]+) FUNCTION ([A-Z0-9]+)\(\ *([A-Z0-9, ]+)\ *\)/
+
+ # Matches e.g. INTEGER INCX,INCY,N
+ VariableDecl =
+ Regexp.compile /\ +(#{Fortran.types_as_regexp})\ +([A-Z,()*0-9 ]+)/
+
+ # Matches e.g. * LDA (input) INTEGER
+ MetaComment =
+ Regexp.compile /\A\*\s*([A-Z0-9,]+)\s+\(([a-zA-Z\/]*)\)/
+
+ # Matches e.g. A, but also DX(*)
+ ArgumentParens =
+ Regexp.compile /[A-Z0-9]+(?: *\([A-Z, 0-9*]+\))?/
+
+
+ # Parse a FORTRAN file, return a Routine object describing the
+ # defined object.
+ #
+ # This function is really tailored towards the blas and lapack
+ # files, although it can in principle parse all FORTRAN types. In
+ # addition, it parses comments to look for metadata, in particular
+ # whether a variable is used as input or output. Lines like
+ #
+ #
+ # * JOBVL (input) CHARACTER*1
+ #
+ # are parsed and the information in parenthesis is extracted.
+ def self.parse_file(f)
+ routine = nil
+ lines = f.readlines
+ lines = Fortran.parse_continuations(lines)
+
+ lines.each do |l|
+ #puts l
+ case l
+ #
+ # parse headings, e.g.
+ #
+ # DOUBLE PRECISION FUNCTION DDOT(N,DX,INCX,DY,INCY)
+ # SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY)
+ #
+ when SubroutineDecl
+ name = $1
+ args = $2.scan /[A-Z0-9]+/
+ routine = Fortran.subroutine name, args
+ when FunctionDecl
+ return_type = $1
+ name = $2
+ args = $3.scan /[A-Z0-9]+/
+ routine = Fortran.function return_type, name, args
+ #
+ # parse argument types, e.g.
+ #
+ # DOUBLE PRECISION DX(*),DY(*)
+ # COMPLEX*16 A( LDA, * ), VL( LDVL, * ), VR( L...
+ #
+ when VariableDecl
+ puts "#$1 -> #$2" if $debug
+ type = $1
+ args = $2.scan ArgumentParens
+ args.each do |argname|
+ puts " #{argname} -> #{type}" if $debug
+ if argname =~ /([A-Z0-9]+)\ *\(.*\)/
+ argname = $1
+ array = true
+ else
+ array = false
+ end
+ if routine.args.member? argname
+ routine.argtype[argname] = Fortran::FortranType.new(type, array)
+ end
+ end
+ #
+ # parse comments which with respect to input/output, e.g.
+ #
+ # * JOBVL (input) CHARACTER*1
+ #
+ when MetaComment
+ args = $1; comment = $2
+ #puts "#{args} -> #{comment}"
+ args.split(',').each do |argname|
+ at = routine.argtype[argname]
+ if at
+ at.comment = comment
+ else
+ puts "Warning: cannot add comment to variable #{argname} in file #{f.path} line \"#{l}\" (argument not defined)"
+ end
+ end
+ end
+ end
+ return routine
+ end
+end
diff --git a/scripts/fortran/c.rb b/scripts/fortran/c.rb
new file mode 100644
index 0000000..35a952b
--- /dev/null
+++ b/scripts/fortran/c.rb
@@ -0,0 +1,175 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+module Fortran
+ module C
+ COMPLEX_TYPE = 'fortran_complext_t'
+ DOUBLE_COMPLEX_TYPE = 'fortran_double_complex_t'
+
+ class Generator < TemplateContext
+ attr_reader :filename, :routines
+
+ def initialize(filename, routines)
+ @filename = filename
+ @routines = routines
+ end
+ end
+
+ def self.generate(template_file, filename, routines)
+ g = Generator.new(filename, routines)
+ g.generate(template_file)
+ end
+
+ def self.reference?(r, argname)
+ argtype = r.argtype[argname]
+ argtype and (argtype.array or argtype.comment =~ /output/)
+ end
+
+ # Generate declaration for wrapper in C.
+ def self.declaration_for r
+ name = r.name.downcase
+ args = []
+
+ if not r.rettype
+ rettype = 'void'
+ elsif r.rettype.basetype == 'COMPLEX*8'
+ rettype = 'void'
+ args << COMPLEX_TYPE + '* retval'
+ elsif r.rettype.basetype == 'COMPLEX*16'
+ rettype = 'void'
+ args << DOUBLE_COMPLEX_TYPE + '* retval'
+ else
+ rettype = C.map_basetype(r.rettype)
+ end
+
+ r.args.each do |argname|
+ argtype = r.argtype[argname]
+ cargname = argname.downcase
+ ctype = C.map_basetype(argtype)
+ ctype << '*' if reference?(r, argname)
+ args << ctype + ' ' + cargname
+ end
+
+ "#{rettype} #{name}(#{args.join ', '})"
+ end
+
+ def self.fortran_declaration_for r
+ name = r.name.downcase + '_'
+ args = []
+
+ if not r.rettype
+ rettype = 'void'
+ elsif r.rettype.basetype == 'COMPLEX*8'
+ rettype = 'void'
+ args << COMPLEX_TYPE + '* retval'
+ elsif r.rettype.basetype == 'COMPLEX*16'
+ rettype = 'void'
+ args << DOUBLE_COMPLEX_TYPE + '* retval';
+ else
+ rettype = C.map_basetype(r.rettype)
+ end
+
+ r.args.each do |argname|
+ argtype = r.argtype[argname]
+ argname = argname.downcase
+ ctype = C.map_basetype(argtype) + '*';
+ args << ctype + ' ' + argname
+ end
+
+ "#{rettype} #{name}(#{args.join ', '})"
+ end
+
+ def self.call_fortran_routine r
+ name = r.name.downcase + '_'
+
+ args = []
+
+ if not r.rettype
+ retstmt = ''
+ elsif r.rettype.basetype == 'COMPLEX*8'
+ retstmt = ''
+ args << 'retval'
+ elsif r.rettype.basetype == 'COMPLEX*16'
+ retstmt = ''
+ args << 'retval'
+ else
+ retstmt = 'return '
+ end
+
+ r.args.each do |argname|
+ if reference?(r, argname)
+ args << argname.downcase
+ else
+ args << '&' + argname.downcase
+ end
+ end
+
+ "#{retstmt}#{name}(#{args.join ', '})"
+ end
+
+ # Generate the actual wrapper.
+ def self.wrapper_for r
+ return <<EOS
+#{declaration_for r}
+{
+ extern #{fortran_declaration_for r};
+ #{call_fortran_routine r};
+}
+EOS
+ end
+
+ def self.map_basetype(type)
+ return 'void' unless type
+ t = ''
+ case type.basetype
+ when 'CHARACTER' then t << 'char'
+ when 'CHARACTER*1' then t << 'char'
+ when /CHARACTER\*[0-9]+/ then t << 'char*'
+ when 'REAL*4' then t << 'float'
+ when 'REAL*8' then t << 'double'
+ when 'INTEGER*2' then t << 'short'
+ when 'INTEGER*4' then t << 'int'
+ when 'INTEGER*8' then t << 'long'
+ when 'LOGICAL*1' then t << 'byte'
+ when 'LOGICAL*2' then t << 'short'
+ when 'LOGICAL*4' then t << 'int'
+ when 'LOGICAL*8' then t << 'long'
+ when 'COMPLEX*8' then t << COMPLEX_TYPE
+ when 'COMPLEX*16' then t << DOUBLE_COMPLEX_TYPE
+ else
+ raise ArgumentError, "Don't know how to convert '#{type}'"
+ end
+ end
+ end
+end
diff --git a/scripts/fortran/java.rb b/scripts/fortran/java.rb
new file mode 100644
index 0000000..184b2ea
--- /dev/null
+++ b/scripts/fortran/java.rb
@@ -0,0 +1,586 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+module Fortran
+
+ class FortranType
+ # extend FortranType by converters to java and C
+ ArrayTypeMap = { 'REAL*4' => 'float[]',
+ 'REAL*8' => 'double[]',
+ 'INTEGER*2' => 'short[]',
+ 'INTEGER*4' => 'int[]',
+ 'INTEGER*8' => 'long[]',
+ 'LOGICAL*1' => 'byte[]',
+ 'LOGICAL*2' => 'short[]',
+ 'LOGICAL*4' => 'int[]',
+ 'LOGICAL*8' => 'long[]',
+ 'COMPLEX*8' => 'float[]',
+ 'COMPLEX*16' => 'double[]',
+ 'VOID' => 'void'
+ }
+
+ StdTypeMap = { 'CHARACTER' => 'char',
+ 'CHARACTER*1' => 'char',
+ 'CHARACTER*N' => 'String',
+ 'REAL*4' => 'float',
+ 'REAL*8' => 'double',
+ 'INTEGER*2' => 'short',
+ 'INTEGER*4' => 'int',
+ 'INTEGER*8' => 'long',
+ 'LOGICAL*1' => 'byte',
+ 'LOGICAL*2' => 'short',
+ 'LOGICAL*4' => 'int',
+ 'LOGICAL*8' => 'long',
+ 'COMPLEX*8' => 'ComplexFloat',
+ 'COMPLEX*16' => 'ComplexDouble',
+ 'VOID' => 'void'
+ }
+
+ # Map a Fortran type to Java type or throw an ArgumentError
+ def to_java
+ if basetype =~ /CHARACTER\*[0-9]+/
+ self.basetype = 'CHARACTER*N'
+ end
+
+ result = if array or comment =~ /output/
+ ArrayTypeMap[basetype]
+ else
+ StdTypeMap[basetype]
+ end
+
+ if not result
+ raise ArgumentError, "Don't know how to convert '#{to_s}'"
+ end
+
+ return result
+ end
+
+ def to_c
+ javatype = to_java
+ if javatype =~ /\[\]$/
+ 'j' + javatype[0...-2] + 'Array'
+ elsif javatype == 'void'
+ 'void'
+ elsif javatype =~ /Complex/
+ 'jobject'
+ else
+ 'j' + javatype.downcase
+ end
+ end
+ end
+
+ # This module contains code for generating Java native declarations
+ # for Fortran routines.
+ module Java
+
+ # Generate
+ def self.generate(template_file, package, class_name, routines)
+ g = Generator.new(package, class_name, routines)
+ g.generate(template_file)
+ end
+
+ ######################################################################
+
+ # A special TemplateContext for Java. In addition, the package
+ # name and classname is stored.
+ #
+ # Usually, you would use the generate method instead of explicitly
+ # constructing an object
+ class Generator < TemplateContext
+ attr_reader :package, :classname, :routines
+
+ # Create a new Generator context. You can use generate
+ # to directly construct and write a template file
+ def initialize(package, classname, routines)
+ @package = package
+ @classname = classname
+ @routines = routines
+ end
+
+ def generate_native_declaration(r)
+ writer = WrapperCodeGenerator.new(header_file_name, r)
+ writer.native_declaration
+ end
+
+ def generate_wrapper(r)
+ writer = WrapperCodeGenerator.new(header_file_name, r)
+ writer.wrapper
+ end
+
+ def header_file_name
+ package.tr('.', '_') + '_' + classname
+ end
+ end
+
+ ######################################################################
+
+ # Generator of wrapper code for one routine, both for Java
+ # (native_declaration) and C (wrapper)
+ class WrapperCodeGenerator
+ attr_reader :prefix
+ attr_accessor :return_type, :fct_name, :decl_args
+ attr_accessor :fortran_args, :fortran_return_type
+ attr_accessor :conversions
+ attr_accessor :call_pre, :call_post, :fortran_fct_name, :call_args
+ attr_accessor :arrays
+
+ def initialize(prefix, r)
+ @package = prefix
+ @routine = r
+ @return_type = ''
+ @fct_name = prefix + '_' + r.name.downcase
+ @decl_args = ''
+ @conversions = ''
+ @fortran_args = []
+ @fortran_return_type = ''
+ @call_pre = ''
+ @fortran_fct_name = ''
+ @call_args = []
+ @call_post = ''
+ @arrays = [] # already seen arrays
+ end
+
+ public
+ # Generate the JNI-wrapper code for the fortran routine.
+ # This is a bit more complex and calls other routines for the different
+ # parts.
+ def wrapper
+ make_fortran_fct_name r.name
+
+ code_for_return_type(r.return_type)
+
+ r.each_arg do |name, type|
+ code_for_argument(name, type)
+ end
+
+ return <<EOS
+JNIEXPORT #{return_type} JNICALL Java_#{fct_name}(JNIEnv *env, jclass this#{decl_args})
+{
+ extern #{fortran_return_type} #{fortran_fct_name}(#{fortran_args.join(', ')});
+
+#{conversions}
+ savedEnv = env;
+ #{call_pre}#{fortran_fct_name}(#{call_args.join(', ')});
+#{call_post}
+}
+EOS
+ end
+
+ # Generate the native function declaration within a Java class.
+ # Everything you need is HERE!
+ def native_declaration
+ begin
+ return_type = ''
+ fct_name = r.name.downcase
+ args = []
+
+ return_type = java_return_type
+
+ r.args.each do |name|
+ type = r.argtype[name]
+ if name != 'INFO'
+ args << type.to_java + " " + name.downcase
+ if type.to_java =~ /\[\]/
+ args << "int #{name.downcase}Idx"
+ end
+ end
+ end
+ result = " public static native #{return_type} #{fct_name}(#{args.join(", ")});"
+ unless r.workspace_arguments.empty?
+ result += "\n" + with_workspace_query
+ end
+ return result
+ rescue
+ puts
+ puts "---Error for routine #{@routine}"
+ puts
+ raise
+ end
+ end
+
+ # Generate Java function with an automatic workspace query.
+ def with_workspace_query
+ args = []
+ r.each_arg do |n, t|
+ unless r.workspace_argument? n or r.workspace_size_argument? n or n == 'INFO'
+ args << t.to_java + " " + n.downcase
+ if t.to_java =~ /\[\]/
+ args << "int #{n.downcase}Idx"
+ end
+ end
+ end
+ return <<EOS
+ public static #{java_return_type} #{r.name.downcase}(#{args.join(", ")}) {
+ int info;
+#{declare_workspace_arrays}
+ info = #{workspace_query};
+ if (info != 0)
+ return info;
+#{allocate_workspaces}
+ info = #{call_with_workspaces};
+ return info;
+ }
+EOS
+ end
+
+ private ############################################################
+
+ # convenience accessor
+ def r; @routine; end
+
+ def java_return_type
+ if r.return_type.basetype == 'VOID' and r.args.last == 'INFO'
+ 'int'
+ else
+ r.return_type.to_java
+ end
+ end
+
+ def make_fortran_fct_name name
+ fortran_fct_name << name.downcase + '_'
+ end
+
+ def code_for_return_type type
+ javatype = type.to_java
+ ctype = type.to_c
+
+ gen = generator(type)
+ gen.set_type(type, javatype, ctype)
+
+ gen.make_return_type
+ gen.make_fortran_return_type
+ gen.make_convert_return_type
+ gen.make_call_return
+ end
+
+ def code_for_argument(name, type)
+ javatype = type.to_java
+ ctype = type.to_c
+ name = name.downcase
+
+ gen = generator(type, name)
+ gen.set_type(type, javatype, ctype)
+ gen.set_name(name)
+
+ gen.make_decl_arg
+ gen.make_fortran_arg
+ gen.make_convert_arg
+ gen.make_call_arg
+ end
+
+ # find the correct code generator for the given type
+ def generator(type, name=nil)
+ javatype = type.to_java
+ #puts javatype
+ #puts name
+ #puts @routine.return_type.basetype
+ g = if javatype == 'void'
+ Java::NilArgument.new(self)
+ elsif javatype == 'int[]' and name == 'info' and @routine.return_type.basetype == 'VOID'
+ Java::InfoArgument.new(self)
+ elsif javatype =~ /\[\]/
+ Java::BufferArgument.new(self)
+ elsif javatype =~ /Complex/
+ Java::ComplexArgument.new(self)
+ elsif javatype == 'char'
+ Java::CharArgument.new(self)
+ else
+ Java::GenericArgument.new(self)
+ end
+ #puts "seleced generator #{g.class}"
+ return g
+ end
+
+ #
+ # Stuff for workspaces below
+ #
+
+ # Declarations for workspace arrays
+ def declare_workspace_arrays
+ r.gen_each_arg do |n, t|
+ if r.workspace_argument? n
+ " #{t.to_java} #{n.downcase} = new #{t.to_java[0..-3]}[1];"
+ elsif r.workspace_size_argument? n
+ " #{t.to_java} #{n.downcase};"
+ end
+ end
+ end
+
+ # Generate a call with the workspace queries
+ def workspace_query
+ return "#{r.name.downcase}(" +
+ r.gen_each_arg(', ') do |n,t|
+ if r.workspace_size_argument? n
+ '-1'
+ elsif n != 'INFO'
+ if t.to_java =~ /\[\]\Z/
+ if r.workspace_argument? n
+ "#{n.downcase}, 0"
+ else
+ "#{n.downcase}, #{n.downcase}Idx"
+ end
+ else
+ n.downcase
+ end
+ end
+ end + ")"
+ end
+
+ # allocate the actual workspaces
+ def allocate_workspaces
+ r.gen_each_arg do |n, t|
+ if r.workspace_argument? n
+ n = n.downcase
+ " l#{n} = (int) #{n}[0]; #{n} = new #{t.to_java[0..-3]}[l#{n}];"
+ end
+ end
+ end
+
+ # call with the allocated workspaces
+ def call_with_workspaces
+ return "#{r.name.downcase}(" +
+ r.gen_each_arg(', ') do |n,t|
+ if n != 'INFO'
+ if t.to_java =~ /\[\]\Z/
+ if r.workspace_argument? n
+ "#{n.downcase}, 0"
+ else
+ "#{n.downcase}, #{n.downcase}Idx"
+ end
+ else
+ n.downcase
+ end
+ end
+ end + ")"
+ end
+ end
+
+ ######################################################################
+ #
+ # Actual code generators
+ #
+
+ # The default case: Just convert types to their java and C
+ # equivalents, pass the reference to the fortran routine and
+ # return the result
+ class GenericArgument
+ attr_reader :code, :type, :javatype, :ctype, :name
+
+ def initialize(code)
+ @code = code
+ end
+
+ def set_type(type, javatype, ctype)
+ @type = type
+ @javatype = javatype
+ @ctype = ctype
+ end
+
+ def set_name(name)
+ @name = name
+ end
+
+ def make_fortran_return_type
+ if ctype == 'jfloat'
+ code.fortran_return_type << 'jdouble'
+ else
+ code.fortran_return_type << ctype
+ end
+ end
+
+ def make_return_type
+ code.return_type << ctype
+ end
+
+ def make_convert_return_type
+ end
+
+ def make_call_return
+ code.call_pre << ctype + " retval = "
+ if ctype == 'jfloat'
+ code.call_post << "\n return (jdouble) retval;"
+ else
+ code.call_post << "\n return retval;"
+ end
+ end
+
+ def make_decl_arg
+ code.decl_args << ", " + ctype + " " + name
+ end
+
+ def make_fortran_arg
+ code.fortran_args << "j" + javatype + " *"
+ end
+
+ def make_convert_arg
+ end
+
+ def make_call_arg
+ code.call_args << "&#{name}"
+ end
+ end
+
+ # For arrays: Add an additional argument to the declaration,
+ # and get the array from the direct buffer
+ class BufferArgument < GenericArgument
+ def make_decl_arg
+ super
+ code.decl_args << ", jint " + name + "Idx"
+ end
+
+ def make_fortran_arg
+ code.fortran_args << "j" + ctype[1...-5] + " *"
+ end
+
+ # Okay, my apologies for this method. What makes it so difficult
+ # is that it can happen that you pass in an array twice. If you
+ # then call Get<Type>ArrayElements twice you get two copies
+ # and any attempt to do something truly inplace won't work (for
+ # example dswap). So I have to check before each array if
+ # I maybe already have it. And the same thing around in the end... .
+ def make_convert_arg
+ basectype = ctype[0...-5]
+ code.conversions << <<EOS + ' '
+ #{basectype} *#{name}PtrBase = 0, *#{name}Ptr = 0;
+ if (#{name}) {
+EOS
+ unless code.arrays.empty?
+ code.arrays.each do |a, t|
+ if t == basectype
+ code.conversions << "if((*env)->IsSameObject(env, #{name}, #{a}) == JNI_TRUE)\n #{name}PtrBase = #{a}PtrBase;\n else\n "
+ end
+ end
+ end
+ code.conversions << <<EOS
+#{name}PtrBase = (*env)->Get#{basectype[1..-1].capitalize}ArrayElements(env, #{name}, NULL);
+ #{name}Ptr = #{name}PtrBase + #{'2*' if type.basetype =~ /COMPLEX/}#{name}Idx;
+ }
+EOS
+
+ # and releasing the stuff again...
+ release = " if(#{name}PtrBase"
+ code.arrays.each do |a, t|
+ if t == basectype
+ release << " && #{name}PtrBase != #{a}PtrBase"
+ end
+ end
+ release << ") {" + <<EOS
+
+ (*env)->Release#{basectype[1..-1].capitalize}ArrayElements(env, #{name}, #{name}PtrBase, 0);
+ }
+EOS
+ code.call_post = release + code.call_post
+
+ # store information about the arrays we have already handled
+ code.arrays << [name, basectype]
+ end
+
+ def make_call_arg
+ code.call_args << "#{name}Ptr"
+ end
+ end
+
+ # For complex values (scalars only!): fortran returns the value in the
+ # first argument, therefore declare the return value, modify the
+ # fortran argument list, and generate the *Complex object.
+ #
+ # for arguments, extract the values from the Java object
+ class ComplexArgument < GenericArgument
+ def make_fortran_return_type
+ code.fortran_args << javatype + " *"
+ code.fortran_return_type << "void"
+ end
+
+ def make_fortran_arg
+ code.fortran_args << javatype + " *"
+ end
+
+ def make_convert_return_type
+ code.conversions << " #{javatype} retval;\n"
+ end
+
+ def make_call_return
+ code.call_post << "\n return create#{javatype}(env, &retval);"
+ code.call_args << "&retval"
+ end
+
+ def make_convert_arg
+ code.conversions << " #{javatype} #{name}Cplx;\n"
+ code.conversions << " get#{javatype}(env, #{name}, &#{name}Cplx);\n"
+ end
+
+ def make_call_arg
+ code.call_args << "&#{name}Cplx"
+ end
+ end
+
+ # For characters: This handles only the first byte. Now idea if it
+ # is really worth dealing with UTF-8 and all the rest...
+ class CharArgument < GenericArgument
+ def make_convert_arg
+ code.conversions << " char #{name}Chr = (char) #{name};\n"
+ end
+
+ def make_call_arg
+ code.call_args << "&#{name}Chr"
+ end
+
+ def make_fortran_arg
+ code.fortran_args << javatype + " *"
+ end
+ end
+
+ # For nil arguments (only return value): don't add a return value
+ class NilArgument < GenericArgument
+ def make_call_return
+ end
+ end
+
+ # For info arguments
+ class InfoArgument < GenericArgument
+ def make_decl_arg
+ code.return_type = 'jint'
+ end
+
+ def make_convert_arg
+ code.conversions << " int info;\n"
+ code.call_post << "\n return info;"
+ end
+
+ def make_fortran_arg
+ code.fortran_args << ctype[1...-5] + " *"
+ end
+ end
+ end # module Java
+end # module Fortran
diff --git a/scripts/fortranwrapper.rb b/scripts/fortranwrapper.rb
new file mode 100644
index 0000000..f616683
--- /dev/null
+++ b/scripts/fortranwrapper.rb
@@ -0,0 +1,134 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+#!/usr/bin/env ruby
+# -*- ruby -*-
+
+# get directory where script resides and add to load path
+Dir.chdir(File.dirname(__FILE__)) { $SCRIPT_DIR = Dir.pwd }
+$LOAD_PATH << $SCRIPT_DIR
+
+#throw "ARGH"
+
+require 'erb'
+require 'optparse'
+
+require 'fortran'
+require 'fortran/java'
+require 'fortran/c'
+
+Banner = <<EOS
+A wrapper of fortran functions for JNI
+written by Mikio L. Braun, mikiobraun at gmail.com
+
+Usage: #{__FILE__} [options] package class file1.f file2.f ...
+EOS
+
+FORTRANWRAPPER_DUMP = 'fortranwrapper.dump'
+
+$here = false
+$force = false
+OptionParser.new do |opts|
+ opts.banner = Banner
+
+ opts.on("-h", "--here", "output files here") {|v| $here = true}
+ opts.on("-f", "--force", "force parsing of fortran file") {|v| $force = true}
+end.parse!
+
+if ARGV.size < 3
+ puts Banner
+ exit
+end
+
+package = ARGV[0]
+klass = ARGV[1]
+
+$debug = false
+
+number_of_routines = 0
+routines = []
+
+if !$force and File.exist?(FORTRANWRAPPER_DUMP)
+ routines = File.open(FORTRANWRAPPER_DUMP) {|f| Marshal.load(f)}
+ puts "Using dumped routines..."
+else
+ # The main loop.
+ # For all files, read the file and loop over all lines.
+ ARGV[2..-1].each do |fn|
+ next if fn =~ /xerbla/ or fn =~ /scabs1/ or fn =~ /dsdot/
+ open(fn) do |f|
+ begin
+ routine = Fortran.parse_file f
+ rescue
+ puts "Error while parsing file #{fn}:"
+ raise
+ end
+ # check whether all arguments have a type associated
+ if not routine.have_all_types?
+ puts routine
+ raise "couldn't parse all types!"
+ end
+
+ number_of_routines += 1
+ routines << routine
+ end
+ end
+end
+
+File.open(FORTRANWRAPPER_DUMP, "w") {|f| Marshal.dump(routines, f)}
+
+#puts "Parsed #{number_of_routines} routines"
+def generate(template_file, package, klass, routines)
+ template_file = File.join($SCRIPT_DIR, template_file)
+ Fortran::Java.generate(template_file, package, klass, routines)
+end
+
+def full_file_path(prefix, package, klass)
+ p = [prefix] + package.split('.') + [ klass ]
+ File.join(p)
+end
+
+java_class = generate('java-class.java', package, klass, routines)
+java_impl = generate('java-impl.c', package, klass, routines)
+
+if $here
+ java_filename = klass + '.java'
+ wrapper_filename = klass + '.c'
+else
+ java_filename = full_file_path('src', package, klass) + '.java'
+ wrapper_filename = File.join('native', klass) + '.c'
+end
+
+File.open(java_filename, 'w') {|o| o.write java_class}
+File.open(wrapper_filename, 'w') {|o| o.write java_impl}
diff --git a/scripts/java-class.java b/scripts/java-class.java
new file mode 100644
index 0000000..7618390
--- /dev/null
+++ b/scripts/java-class.java
@@ -0,0 +1,60 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package <%= package %>;
+
+import org.jblas.core.ComplexFloat;
+import org.jblas.core.ComplexDouble;
+
+public class <%= classname %> {
+
+ static {
+ try {
+ System.loadLibrary("j<%= classname.downcase %>");
+ }
+ catch(UnsatisfiedLinkError e) {
+ System.err.println(
+ "BLAS native library not found in path. Copying native library\n" +
+ "from the archive. Consider installing the library somewhere\n" +
+ "in the path (for Windows: PATH, for Linux: LD_LIBRARY_PATH).");
+ new org.jblas.util.LibraryLoader().loadLibrary("j<%= classname.downcase %>");
+ }
+ }
+
+<% for r in routines -%>
+<%= generate_native_declaration r %>
+<% end %>
+}
diff --git a/scripts/java-impl.c b/scripts/java-impl.c
new file mode 100644
index 0000000..071f21c
--- /dev/null
+++ b/scripts/java-impl.c
@@ -0,0 +1,161 @@
+/// --- BEGIN LICENSE BLOCK ---
+// Copyright (c) 2009, Mikio L. Braun
+// 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 Technische Universität Berlin 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
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/// --- END LICENSE BLOCK ---
+
+#include "<%= header_file_name %>.h"
+
+#define CORE_PACKAGE "org/jblas/core/"
+
+/*
+ * For convenience, we define some typedefs here which have the
+ * same name as certain Java types, but their implementation differs (of course)
+ */
+typedef struct { float real, imag; } ComplexFloat;
+typedef struct { double real, imag; } ComplexDouble;
+typedef char *String;
+
+typedef char ByteBuffer;
+typedef short ShortBuffer;
+typedef int IntBuffer;
+typedef long LongBuffer;
+typedef float FloatBuffer;
+typedef double DoubleBuffer;
+
+/* a function to create new objects */
+static jobject createObject(JNIEnv *env, const char *className, const char *signature, ...)
+{
+ va_list args;
+ jclass klass = (*env)->FindClass(env, className);
+ jmethodID init = (*env)->GetMethodID(env, klass, "<init>", signature);
+ jobject newObject;
+
+ va_start(args, signature);
+ newObject = (*env)->NewObjectV(env, klass, init, args);
+ va_end(args);
+}
+
+static jobject createComplexFloat(JNIEnv *env, ComplexFloat *fc)
+{
+ return createObject(env, CORE_PACKAGE "ComplexFloat", "(FF)V", fc->real, fc->imag);
+}
+
+static jobject createComplexDouble(JNIEnv *env, ComplexDouble *dc)
+{
+ return createObject(env, CORE_PACKAGE "ComplexDouble", "(DD)V", dc->real, dc->imag);
+}
+
+static void getComplexFloat(JNIEnv *env, jobject fc, ComplexFloat *result)
+{
+ jclass klass = (*env)->FindClass(env, CORE_PACKAGE "ComplexFloat");
+ jfieldID reField = (*env)->GetFieldID(env, klass, "r", "F");
+ jfieldID imField = (*env)->GetFieldID(env, klass, "i", "F");
+
+ result->real = (*env)->GetFloatField(env, fc, reField);
+ result->imag = (*env)->GetFloatField(env, fc, imField);
+}
+
+static void getComplexDouble(JNIEnv *env, jobject dc, ComplexDouble *result)
+{
+ jclass klass = (*env)->FindClass(env, CORE_PACKAGE "ComplexDouble");
+ jfieldID reField = (*env)->GetFieldID(env, klass, "r", "D");
+ jfieldID imField = (*env)->GetFieldID(env, klass, "i", "D");
+
+ result->real = (*env)->GetDoubleField(env, dc, reField);
+ result->imag = (*env)->GetDoubleField(env, dc, imField);
+}
+
+static void throwIllegalArgumentException(JNIEnv *env, const char *message)
+{
+ jclass klass = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
+
+ (*env)->ThrowNew(env, klass, message);
+}
+
+/**********************************************************************/
+/* XERBLA function arguments */
+/**********************************************************************/
+
+static char *routine_names[] = {
+<% for r in routines.sort {|r1, r2| r1.name <=> r2.name} %> "<%= r.name %>", <% end -%>
+ 0
+};
+
+static char *routine_arguments[][<%= (routines.map do |r| r.args.length end).max %>] = {
+<% for r in routines.sort {|r1, r2| r1.name <=> r2.name} -%>
+ { <%= (r.args.map do |s| '"' + s + '"' end).join(', ') %> },
+<% end -%>
+};
+
+/**********************************************************************/
+/* Our implementation of XERBLA */
+/**********************************************************************/
+static JNIEnv *savedEnv = 0;
+
+
+void xerbla_(char *fct, int *info)
+{
+ static char name[7];
+ static char buffer[256];
+ int i;
+ char **p;
+ char **arguments = 0;
+
+ for (i = 0; i < 6; i++) {
+ if (fct[i] == ' ')
+ break;
+ name[i] = fct[i];
+ }
+ name[i] = '\0';
+
+ //fprintf(stderr, "Searching for function \"%s\"\n", name);
+
+ for (p = routine_names, i = 0; *p; p++, i++)
+ if (!strcmp(*p, name))
+ arguments = routine_arguments[i];
+
+ if (!arguments) {
+ sprintf(buffer, "XERBLA: Error on argument %d for *unknown function* %s (how odd!)\n", *info, name);
+ }
+ else {
+ sprintf(buffer, "XERBLA: Error on argument %d (%s) in %s", *info, arguments[*info-1], name);
+ }
+ throwIllegalArgumentException(savedEnv, buffer);
+}
+
+/**********************************************************************/
+/* generated functions below */
+/**********************************************************************/
+
+<% for r in routines %>
+<%= generate_wrapper r -%>
+<% end %>
diff --git a/scripts/render-textile.rb b/scripts/render-textile.rb
new file mode 100644
index 0000000..128e766
--- /dev/null
+++ b/scripts/render-textile.rb
@@ -0,0 +1,45 @@
+require 'set'
+
+require 'rubygems'
+require 'redcloth'
+
+def link_to_package(txt, pkg)
+ txt.gsub!(pkg,
+ "<a href=\"#{pkg.tr('.', '/')}/package-summary.html\">#{pkg}</a>")
+end
+
+def link_to_class(txt, cls)
+ fullname = SOURCES.
+ grep(Regexp.new(cls))[0].
+ tr('.', '/').
+ gsub('/java', '.html').
+ gsub('src/', '')
+ txt.gsub!(/(\W)#{cls}(\W)/) do |m|
+ $1 + "<a href=\"#{fullname}\">#{cls}</a>" + $2
+ end
+end
+
+SOURCES = Dir.glob('src/**/*.java')
+CLASSES = SOURCES.map {|f| File.basename(f, '.java')}
+PACKAGES = Set.new(SOURCES.map {|f| File.dirname(f)})
+
+#puts "Classes:"
+#CLASSES.each {|c| puts c}
+#puts
+#puts "Packages:"
+#PACKAGES.each {|p| puts p}
+
+#exit
+
+ARGV.each do |f|
+ newf = f.gsub /.textile$/, '.html'
+ out = open(newf, 'w') do |o|
+ txt = open(f, 'r').read
+ html = RedCloth.new(txt).to_html
+ html.gsub!(/<br \/>/, '')
+ html.gsub!(/<table>/, '<table class="my">')
+ PACKAGES.each {|p| link_to_package(html, p)}
+ CLASSES.each {|c| link_to_class(html, c)}
+ o.write('<html><body>' + html + '</body></html>')
+ end
+end
diff --git a/scripts/rjpp.rb b/scripts/rjpp.rb
new file mode 100644
index 0000000..458aaf6
--- /dev/null
+++ b/scripts/rjpp.rb
@@ -0,0 +1,95 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+#!/usr/bin/ruby
+#
+# The Ruby Java PreProcessor
+#
+# Contrary to the "usual" cpp, commands will be expanded "in-place" in
+# an idempotent fashion (meaning that you can run rjpp on the same
+# file more than once.
+#
+# Directives are either given as
+#
+# /*# ... directive ... #*/
+#
+# After expansion, the code will look like this:
+#
+# /*# original directive #*/
+# //RJPP-BEGIN------------------------------------------------------------
+# expanded code
+# //RJPP-END--------------------------------------------------------------
+#
+# So you can run the rjpp twice on a file and get the same result as
+# running it once. This property is called idempotency in mathematics X-D
+
+
+# print usage
+if ARGV.length == 0
+ puts "Usage: jrpp file"
+end
+
+def collect(*args)
+ args.join "\n"
+end
+
+def doc(s)
+ "/** " + s + " */"
+end
+
+#open file
+file = open(ARGV[0], 'r').read
+saved_file = file
+
+# remove existing expansions
+file.gsub! /\/\/RJPP-BEGIN.*?\/\/RJPP-END[^\n]*\n/m, ''
+
+# expand code
+file.gsub! /\/\*\#(.*?)\#\*\//m do |s|
+ expansion = eval($1).to_s
+ result = s
+ unless expansion.empty?
+ result << "\n//RJPP-BEGIN------------------------------------------------------------\n" + expansion + "//RJPP-END--------------------------------------------------------------"
+ end
+ result
+end
+
+# write file
+if file.length == 0
+ puts "How odd... The whole file magically vanished..."
+else
+ open(ARGV[0] + '.rjpp', 'w').write(saved_file)
+ open(ARGV[0], 'w').write(file)
+ #print file
+end
diff --git a/scripts/static_class_to_float.rb b/scripts/static_class_to_float.rb
new file mode 100644
index 0000000..7aa9d9a
--- /dev/null
+++ b/scripts/static_class_to_float.rb
@@ -0,0 +1,109 @@
+## --- BEGIN LICENSE BLOCK ---
+# Copyright (c) 2009, Mikio L. Braun
+# 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 Technische Universität Berlin 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
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## --- END LICENSE BLOCK ---
+
+def readfile(fn)
+ f = open(fn)
+ s = f.read
+ f.close
+ s
+end
+
+def writefile(fn, s)
+ f = open(fn, 'w')
+ f.write s
+ f.close
+end
+
+def classfile(classname)
+ classname.tr('.', File::SEPARATOR) + '.java'
+end
+
+def translate(cl, s)
+ mark = "public class #{cl.split('.').last} {\n"
+ i = s.index(mark) + mark.length
+ j = s.rindex('}')
+ head = s[0...i]
+ body = s[i...j]
+
+ # remove part copied in last time
+ body.gsub! /\/\/BEGIN.*?\/\/END\n/m, ''
+
+ copybody = body.dup
+
+ # remove part which should not be added as float
+ copybody.gsub! /\/\/STOP.*?\/\/START\n/m, ''
+
+ # do necessary substitutions
+ copybody.gsub! /DoubleMatrix/, 'FloatMatrix'
+ copybody.gsub! /DoubleBuffer/, 'FloatBuffer'
+ copybody.gsub! /DoubleVector/, 'FloatVector'
+ copybody.gsub! /ComplexDouble/, 'ComplexFloat'
+ copybody.gsub! /([0-9]+\.[0-9]+)/, '\1f'
+ copybody.gsub! /double/, 'float'
+ copybody.gsub! /Blas\.dz/, 'Blas.sc'
+ copybody.gsub! /Blas\.d/, 'Blas.s'
+ copybody.gsub! /Blas\.z/, 'Blas.c'
+ copybody.gsub! /Blas\.idamax/, 'Blas.isamax'
+ copybody.gsub! /Blas\.izamax/, 'Blas.icamax'
+ copybody.gsub!(/([a-z]+)Double/, '\1Float')
+
+ # construct output file
+ out = []
+ out << head
+ out << body
+ out << "//BEGIN\n"
+ out << " // The code below has been automatically generated.\n"
+ out << " // DO NOT EDIT!\n"
+ out << copybody
+ out << "//END\n"
+ out << "}\n"
+ return out.join
+end
+
+if ARGV.size < 2
+ puts "Usage: ruby static_class_to_float.rb srcprefix classname"
+ exit
+end
+
+prefix = ARGV[0]
+source = ARGV[1]
+
+fn = File.join(prefix, classfile(source))
+
+if File.exist? fn
+ s = readfile(fn)
+ writefile(fn, translate(source, s))
+else
+ puts "Could not read file #{fn}"
+end
diff --git a/scripts/test_fortranwrapper b/scripts/test_fortranwrapper
new file mode 100644
index 0000000..435c65d
--- /dev/null
+++ b/scripts/test_fortranwrapper
@@ -0,0 +1,4 @@
+#scripts/fortranwrapper com.fhg.la Blas ~/src/blas/ddot.f ~/src/blas/zdotc.f ~/src/blas/saxpy.f ~/src/blas/cdotc.f ~/src/blas/zgemm.f
+scripts/fortranwrapper com.fhg.la Blas ~/src/blas/*.f
+ant compile createHeaderFiles
+make bin/Blas.o
\ No newline at end of file
diff --git a/src/org/jblas/core/ComplexDouble.java b/src/org/jblas/core/ComplexDouble.java
new file mode 100644
index 0000000..b8e6e73
--- /dev/null
+++ b/src/org/jblas/core/ComplexDouble.java
@@ -0,0 +1,322 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.core;
+
+import static java.lang.Math.sqrt;
+
+import java.nio.DoubleBuffer;
+
+/**
+ * A complex value with double precision.
+ *
+ * @author Mikio L. Braun
+ *
+ */
+public class ComplexDouble {
+
+ private double r, i;
+ public static final ComplexDouble UNIT = new ComplexDouble(1.0, 0.0);
+ public static final ComplexDouble I = new ComplexDouble(0.0, 1.0);
+ public static final ComplexDouble NEG_UNIT = new ComplexDouble(-1.0, 0.0);
+ public static final ComplexDouble NEG_I = new ComplexDouble(0.0, -1.0);
+ public static final ComplexDouble ZERO = new ComplexDouble(0.0);
+
+ public ComplexDouble(double real, double imag) {
+ r = real;
+ i = imag;
+ }
+
+ public ComplexDouble(double real) {
+ this(real, 0.0);
+ }
+
+ public String toString() {
+ if (i >= 0) {
+ return r + " + " + i + "i";
+ } else {
+ return r + " - " + (-i) + "i";
+ }
+ }
+
+ public ComplexDouble set(double real, double imag) {
+ r = real;
+ i = imag;
+ return this;
+ }
+
+ public double real() {
+ return r;
+ }
+
+ public double imag() {
+ return i;
+ }
+
+ public ComplexDouble dup() {
+ return new ComplexDouble(r, i);
+ }
+
+ public ComplexDouble copy(ComplexDouble other) {
+ r = other.r;
+ i = other.i;
+ return this;
+ }
+
+ /** Add two complex numbers in-place */
+ public ComplexDouble addi(ComplexDouble c, ComplexDouble result) {
+ if (this == result) {
+ r += c.r;
+ i += c.i;
+ } else {
+ result.r = r + c.r;
+ result.i = i + c.i;
+ }
+ return result;
+ }
+
+ /** Add two complex numbers in-place storing the result in this. */
+ public ComplexDouble addi(ComplexDouble c) {
+ return addi(c, this);
+ }
+
+ /** Add two complex numbers. */
+ public ComplexDouble add(ComplexDouble c) {
+ return dup().addi(c);
+ }
+
+ /** Add a real number to a complex number in-place. */
+ public ComplexDouble addi(double a, ComplexDouble result) {
+ if (this == result) {
+ r += a;
+ } else {
+ result.r = r + a;
+ result.i = i;
+ }
+ return result;
+ }
+
+ /** Add a real number to complex number in-place, storing the result in this. */
+ public ComplexDouble addi(double c) {
+ return addi(c, this);
+ }
+
+ /** Add a real number to a complex number. */
+ public ComplexDouble add(double c) {
+ return dup().addi(c);
+ }
+
+ /** Subtract two complex numbers, in-place */
+ public ComplexDouble subi(ComplexDouble c, ComplexDouble result) {
+ if (this == result) {
+ r -= c.r;
+ i -= c.i;
+ } else {
+ result.r = r - c.r;
+ result.i = i - c.i;
+ }
+ return this;
+ }
+
+ public ComplexDouble subi(ComplexDouble c) {
+ return subi(c, this);
+ }
+
+ /** Subtract two complex numbers */
+ public ComplexDouble sub(ComplexDouble c) {
+ return dup().subi(c);
+ }
+
+ public ComplexDouble subi(double a, ComplexDouble result) {
+ if (this == result) {
+ r -= a;
+ } else {
+ result.r = r - a;
+ result.i = i;
+ }
+ return result;
+ }
+
+ public ComplexDouble subi(double a) {
+ return subi(a, this);
+ }
+
+ public ComplexDouble sub(double r) {
+ return dup().subi(r);
+ }
+
+ /** Multiply two complex numbers, inplace */
+ public ComplexDouble muli(ComplexDouble c, ComplexDouble result) {
+ double newR = r * c.r - i * c.i;
+ double newI = r * c.i + i * c.r;
+ result.r = newR;
+ result.i = newI;
+ return result;
+ }
+
+ public ComplexDouble muli(ComplexDouble c) {
+ return muli(c, this);
+ }
+
+ /** Multiply two complex numbers */
+ public ComplexDouble mul(ComplexDouble c) {
+ return dup().muli(c);
+ }
+
+ public ComplexDouble mul(double v) {
+ return dup().muli(v);
+ }
+
+ public ComplexDouble muli(double v, ComplexDouble result) {
+ if (this == result) {
+ r *= v;
+ i *= v;
+ } else {
+ result.r = r * v;
+ result.i = i * v;
+ }
+ return this;
+ }
+
+ public ComplexDouble muli(double v) {
+ return muli(v, this);
+ }
+
+ /** Divide two complex numbers */
+ public ComplexDouble div(ComplexDouble c) {
+ return dup().divi(c);
+ }
+
+ /** Divide two complex numbers, in-place */
+ public ComplexDouble divi(ComplexDouble c, ComplexDouble result) {
+ double d = c.r * c.r + c.i * c.i;
+ double newR = (r * c.r + i * c.i) / d;
+ double newI = (i * c.r - r * c.i) / d;
+ result.r = newR;
+ result.i = newI;
+ return result;
+ }
+
+ public ComplexDouble divi(ComplexDouble c) {
+ return divi(c, this);
+ }
+
+ public ComplexDouble divi(double v, ComplexDouble result) {
+ if (this == result) {
+ r /= v;
+ i /= v;
+ } else {
+ result.r = r / v;
+ result.i = i / v;
+ }
+ return this;
+ }
+
+ public ComplexDouble divi(double v) {
+ return divi(v, this);
+ }
+
+ public ComplexDouble div(double v) {
+ return dup().divi(v);
+ }
+
+ /** Return the absolute value */
+ public double abs() {
+ return (double) sqrt(r * r + i * i);
+ }
+
+ public ComplexDouble invi() {
+ double d = r * r + i * i;
+ r = r / d;
+ i = -i / d;
+ return this;
+ }
+
+ public ComplexDouble inv() {
+ return dup().invi();
+ }
+
+ public ComplexDouble neg() {
+ return dup().negi();
+ }
+
+ public ComplexDouble negi() {
+ r = -r;
+ i = -i;
+ return this;
+ }
+
+ public ComplexDouble conji() {
+ i = -i;
+ return this;
+ }
+
+ public ComplexDouble conj() {
+ return dup().conji();
+ }
+
+ /**
+ * Comparing two DoubleComplex values.
+ */
+ public boolean equals(Object o) {
+ if (!(o instanceof ComplexDouble)) {
+ return false;
+ }
+ ComplexDouble c = (ComplexDouble) o;
+
+ return eq(c);
+ }
+
+ public boolean eq(ComplexDouble c) {
+ return Math.abs(r - c.r) + Math.abs(i - c.i) < (double) 1e-6;
+ }
+
+ public boolean ne(ComplexDouble c) {
+ return !eq(c);
+ }
+
+ public boolean isZero() {
+ return r == 0.0 && i == 0.0;
+ }
+
+ public boolean isReal() {
+ return i == 0.0;
+ }
+
+ public boolean isImag() {
+ return r == 0.0;
+ }
+}
diff --git a/src/org/jblas/core/ComplexFloat.java b/src/org/jblas/core/ComplexFloat.java
new file mode 100644
index 0000000..de1c885
--- /dev/null
+++ b/src/org/jblas/core/ComplexFloat.java
@@ -0,0 +1,322 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.core;
+
+import static java.lang.Math.sqrt;
+
+import java.nio.FloatBuffer;
+
+/**
+ * A complex value with float precision.
+ *
+ * @author Mikio L. Braun
+ *
+ */
+public class ComplexFloat {
+
+ private float r, i;
+ public static final ComplexFloat UNIT = new ComplexFloat(1.0f, 0.0f);
+ public static final ComplexFloat I = new ComplexFloat(0.0f, 1.0f);
+ public static final ComplexFloat NEG_UNIT = new ComplexFloat(-1.0f, 0.0f);
+ public static final ComplexFloat NEG_I = new ComplexFloat(0.0f, -1.0f);
+ public static final ComplexFloat ZERO = new ComplexFloat(0.0f);
+
+ public ComplexFloat(float real, float imag) {
+ r = real;
+ i = imag;
+ }
+
+ public ComplexFloat(float real) {
+ this(real, 0.0f);
+ }
+
+ public String toString() {
+ if (i >= 0) {
+ return r + " + " + i + "i";
+ } else {
+ return r + " - " + (-i) + "i";
+ }
+ }
+
+ public ComplexFloat set(float real, float imag) {
+ r = real;
+ i = imag;
+ return this;
+ }
+
+ public float real() {
+ return r;
+ }
+
+ public float imag() {
+ return i;
+ }
+
+ public ComplexFloat dup() {
+ return new ComplexFloat(r, i);
+ }
+
+ public ComplexFloat copy(ComplexFloat other) {
+ r = other.r;
+ i = other.i;
+ return this;
+ }
+
+ /** Add two complex numbers in-place */
+ public ComplexFloat addi(ComplexFloat c, ComplexFloat result) {
+ if (this == result) {
+ r += c.r;
+ i += c.i;
+ } else {
+ result.r = r + c.r;
+ result.i = i + c.i;
+ }
+ return result;
+ }
+
+ /** Add two complex numbers in-place storing the result in this. */
+ public ComplexFloat addi(ComplexFloat c) {
+ return addi(c, this);
+ }
+
+ /** Add two complex numbers. */
+ public ComplexFloat add(ComplexFloat c) {
+ return dup().addi(c);
+ }
+
+ /** Add a real number to a complex number in-place. */
+ public ComplexFloat addi(float a, ComplexFloat result) {
+ if (this == result) {
+ r += a;
+ } else {
+ result.r = r + a;
+ result.i = i;
+ }
+ return result;
+ }
+
+ /** Add a real number to complex number in-place, storing the result in this. */
+ public ComplexFloat addi(float c) {
+ return addi(c, this);
+ }
+
+ /** Add a real number to a complex number. */
+ public ComplexFloat add(float c) {
+ return dup().addi(c);
+ }
+
+ /** Subtract two complex numbers, in-place */
+ public ComplexFloat subi(ComplexFloat c, ComplexFloat result) {
+ if (this == result) {
+ r -= c.r;
+ i -= c.i;
+ } else {
+ result.r = r - c.r;
+ result.i = i - c.i;
+ }
+ return this;
+ }
+
+ public ComplexFloat subi(ComplexFloat c) {
+ return subi(c, this);
+ }
+
+ /** Subtract two complex numbers */
+ public ComplexFloat sub(ComplexFloat c) {
+ return dup().subi(c);
+ }
+
+ public ComplexFloat subi(float a, ComplexFloat result) {
+ if (this == result) {
+ r -= a;
+ } else {
+ result.r = r - a;
+ result.i = i;
+ }
+ return result;
+ }
+
+ public ComplexFloat subi(float a) {
+ return subi(a, this);
+ }
+
+ public ComplexFloat sub(float r) {
+ return dup().subi(r);
+ }
+
+ /** Multiply two complex numbers, inplace */
+ public ComplexFloat muli(ComplexFloat c, ComplexFloat result) {
+ float newR = r * c.r - i * c.i;
+ float newI = r * c.i + i * c.r;
+ result.r = newR;
+ result.i = newI;
+ return result;
+ }
+
+ public ComplexFloat muli(ComplexFloat c) {
+ return muli(c, this);
+ }
+
+ /** Multiply two complex numbers */
+ public ComplexFloat mul(ComplexFloat c) {
+ return dup().muli(c);
+ }
+
+ public ComplexFloat mul(float v) {
+ return dup().muli(v);
+ }
+
+ public ComplexFloat muli(float v, ComplexFloat result) {
+ if (this == result) {
+ r *= v;
+ i *= v;
+ } else {
+ result.r = r * v;
+ result.i = i * v;
+ }
+ return this;
+ }
+
+ public ComplexFloat muli(float v) {
+ return muli(v, this);
+ }
+
+ /** Divide two complex numbers */
+ public ComplexFloat div(ComplexFloat c) {
+ return dup().divi(c);
+ }
+
+ /** Divide two complex numbers, in-place */
+ public ComplexFloat divi(ComplexFloat c, ComplexFloat result) {
+ float d = c.r * c.r + c.i * c.i;
+ float newR = (r * c.r + i * c.i) / d;
+ float newI = (i * c.r - r * c.i) / d;
+ result.r = newR;
+ result.i = newI;
+ return result;
+ }
+
+ public ComplexFloat divi(ComplexFloat c) {
+ return divi(c, this);
+ }
+
+ public ComplexFloat divi(float v, ComplexFloat result) {
+ if (this == result) {
+ r /= v;
+ i /= v;
+ } else {
+ result.r = r / v;
+ result.i = i / v;
+ }
+ return this;
+ }
+
+ public ComplexFloat divi(float v) {
+ return divi(v, this);
+ }
+
+ public ComplexFloat div(float v) {
+ return dup().divi(v);
+ }
+
+ /** Return the absolute value */
+ public float abs() {
+ return (float) sqrt(r * r + i * i);
+ }
+
+ public ComplexFloat invi() {
+ float d = r * r + i * i;
+ r = r / d;
+ i = -i / d;
+ return this;
+ }
+
+ public ComplexFloat inv() {
+ return dup().invi();
+ }
+
+ public ComplexFloat neg() {
+ return dup().negi();
+ }
+
+ public ComplexFloat negi() {
+ r = -r;
+ i = -i;
+ return this;
+ }
+
+ public ComplexFloat conji() {
+ i = -i;
+ return this;
+ }
+
+ public ComplexFloat conj() {
+ return dup().conji();
+ }
+
+ /**
+ * Comparing two DoubleComplex values.
+ */
+ public boolean equals(Object o) {
+ if (!(o instanceof ComplexFloat)) {
+ return false;
+ }
+ ComplexFloat c = (ComplexFloat) o;
+
+ return eq(c);
+ }
+
+ public boolean eq(ComplexFloat c) {
+ return Math.abs(r - c.r) + Math.abs(i - c.i) < (float) 1e-6;
+ }
+
+ public boolean ne(ComplexFloat c) {
+ return !eq(c);
+ }
+
+ public boolean isZero() {
+ return r == 0.0f && i == 0.0f;
+ }
+
+ public boolean isReal() {
+ return i == 0.0f;
+ }
+
+ public boolean isImag() {
+ return r == 0.0f;
+ }
+}
diff --git a/src/org/jblas/core/Functions.java b/src/org/jblas/core/Functions.java
new file mode 100644
index 0000000..8573ea8
--- /dev/null
+++ b/src/org/jblas/core/Functions.java
@@ -0,0 +1,46 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.core;
+
+public class Functions {
+ public static double sinc(double x) {
+ if (x == 0)
+ return 1.0;
+ else
+ return Math.sin(Math.PI * x) / (Math.PI * x);
+ }
+}
diff --git a/src/org/jblas/core/package-info.java b/src/org/jblas/core/package-info.java
new file mode 100644
index 0000000..0f9901a
--- /dev/null
+++ b/src/org/jblas/core/package-info.java
@@ -0,0 +1,42 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/**
+ * Support classes for jBLAS.
+ *
+ * This package contains several base classes, for example complex data types.
+ */
+package org.jblas.core;
diff --git a/src/org/jblas/la/Blas.java b/src/org/jblas/la/Blas.java
new file mode 100644
index 0000000..6d7c62d
--- /dev/null
+++ b/src/org/jblas/la/Blas.java
@@ -0,0 +1,378 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.core.ComplexFloat;
+import org.jblas.core.ComplexDouble;
+
+public class Blas {
+
+ static {
+ try {
+ System.loadLibrary("jblas");
+ }
+ catch(UnsatisfiedLinkError e) {
+ System.err.println(
+ "BLAS native library not found in path. Copying native library\n" +
+ "from the archive. Consider installing the library somewhere\n" +
+ "in the path (for Windows: PATH, for Linux: LD_LIBRARY_PATH).");
+ new org.jblas.util.LibraryLoader().loadLibrary("jblas");
+ }
+ }
+
+ public static native void caxpy(int n, ComplexFloat ca, float[] cx, int cxIdx, int incx, float[] cy, int cyIdx, int incy);
+ public static native void ccopy(int n, float[] cx, int cxIdx, int incx, float[] cy, int cyIdx, int incy);
+ public static native ComplexFloat cdotc(int n, float[] cx, int cxIdx, int incx, float[] cy, int cyIdx, int incy);
+ public static native ComplexFloat cdotu(int n, float[] cx, int cxIdx, int incx, float[] cy, int cyIdx, int incy);
+ public static native void cgbmv(char trans, int m, int n, int kl, int ku, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx, ComplexFloat beta, float[] y, int yIdx, int incy);
+ public static native void cgemm(char transa, char transb, int m, int n, int k, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb, ComplexFloat beta, float[] c, int cIdx, int ldc);
+ public static native void cgemv(char trans, int m, int n, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx, ComplexFloat beta, float[] y, int yIdx, int incy);
+ public static native void cgerc(int m, int n, ComplexFloat alpha, float[] x, int xIdx, int incx, float[] y, int yIdx, int incy, float[] a, int aIdx, int lda);
+ public static native void cgeru(int m, int n, ComplexFloat alpha, float[] x, int xIdx, int incx, float[] y, int yIdx, int incy, float[] a, int aIdx, int lda);
+ public static native void chbmv(char uplo, int n, int k, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx, ComplexFloat beta, float[] y, int yIdx, int incy);
+ public static native void chemm(char side, char uplo, int m, int n, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb, ComplexFloat beta, float[] c, int cIdx, int ldc);
+ public static native void chemv(char uplo, int n, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx, ComplexFloat beta, float[] y, int yIdx, int incy);
+ public static native void cher2(char uplo, int n, ComplexFloat alpha, float[] x, int xIdx, int incx, float[] y, int yIdx, int incy, float[] a, int aIdx, int lda);
+ public static native void cher2k(char uplo, char trans, int n, int k, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb, float beta, float[] c, int cIdx, int ldc);
+ public static native void cher(char uplo, int n, float alpha, float[] x, int xIdx, int incx, float[] a, int aIdx, int lda);
+ public static native void cherk(char uplo, char trans, int n, int k, float alpha, float[] a, int aIdx, int lda, float beta, float[] c, int cIdx, int ldc);
+ public static native void chpmv(char uplo, int n, ComplexFloat alpha, float[] ap, int apIdx, float[] x, int xIdx, int incx, ComplexFloat beta, float[] y, int yIdx, int incy);
+ public static native void chpr2(char uplo, int n, ComplexFloat alpha, float[] x, int xIdx, int incx, float[] y, int yIdx, int incy, float[] ap, int apIdx);
+ public static native void chpr(char uplo, int n, float alpha, float[] x, int xIdx, int incx, float[] ap, int apIdx);
+ public static native void crotg(ComplexFloat ca, ComplexFloat cb, float c, ComplexFloat s);
+ public static native void cscal(int n, ComplexFloat ca, float[] cx, int cxIdx, int incx);
+ public static native void csrot(int n, float[] cx, int cxIdx, int incx, float[] cy, int cyIdx, int incy, float c, float s);
+ public static native void csscal(int n, float sa, float[] cx, int cxIdx, int incx);
+ public static native void cswap(int n, float[] cx, int cxIdx, int incx, float[] cy, int cyIdx, int incy);
+ public static native void csymm(char side, char uplo, int m, int n, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb, ComplexFloat beta, float[] c, int cIdx, int ldc);
+ public static native void csyr2k(char uplo, char trans, int n, int k, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb, ComplexFloat beta, float[] c, int cIdx, int ldc);
+ public static native void csyrk(char uplo, char trans, int n, int k, ComplexFloat alpha, float[] a, int aIdx, int lda, ComplexFloat beta, float[] c, int cIdx, int ldc);
+ public static native void ctbmv(char uplo, char trans, char diag, int n, int k, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx);
+ public static native void ctbsv(char uplo, char trans, char diag, int n, int k, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx);
+ public static native void ctpmv(char uplo, char trans, char diag, int n, float[] ap, int apIdx, float[] x, int xIdx, int incx);
+ public static native void ctpsv(char uplo, char trans, char diag, int n, float[] ap, int apIdx, float[] x, int xIdx, int incx);
+ public static native void ctrmm(char side, char uplo, char transa, char diag, int m, int n, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb);
+ public static native void ctrmv(char uplo, char trans, char diag, int n, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx);
+ public static native void ctrsm(char side, char uplo, char transa, char diag, int m, int n, ComplexFloat alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb);
+ public static native void ctrsv(char uplo, char trans, char diag, int n, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx);
+ public static native double dasum(int n, double[] dx, int dxIdx, int incx);
+ public static native void daxpy(int n, double da, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy);
+ public static native double dcabs1(ComplexDouble z);
+ public static native void dcopy(int n, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy);
+ public static native double ddot(int n, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy);
+ public static native void dgbmv(char trans, int m, int n, int kl, int ku, double alpha, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx, double beta, double[] y, int yIdx, int incy);
+ public static native void dgemm(char transa, char transb, int m, int n, int k, double alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb, double beta, double[] c, int cIdx, int ldc);
+ public static native void dgemv(char trans, int m, int n, double alpha, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx, double beta, double[] y, int yIdx, int incy);
+ public static native void dger(int m, int n, double alpha, double[] x, int xIdx, int incx, double[] y, int yIdx, int incy, double[] a, int aIdx, int lda);
+ public static native double dnrm2(int n, double[] x, int xIdx, int incx);
+ public static native void drot(int n, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy, double c, double s);
+ public static native void drotg(double da, double db, double c, double s);
+ public static native void drotm(int n, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy, double[] dparam, int dparamIdx);
+ public static native void drotmg(double[] dd1, int dd1Idx, double[] dd2, int dd2Idx, double[] dx1, int dx1Idx, double dy1, double[] dparam, int dparamIdx);
+ public static native void dsbmv(char uplo, int n, int k, double alpha, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx, double beta, double[] y, int yIdx, int incy);
+ public static native void dscal(int n, double da, double[] dx, int dxIdx, int incx);
+ public static native double dsdot(int n, float[] sx, int sxIdx, int incx, float[] sy, int syIdx, int incy);
+ public static native void dspmv(char uplo, int n, double alpha, double[] ap, int apIdx, double[] x, int xIdx, int incx, double beta, double[] y, int yIdx, int incy);
+ public static native void dspr2(char uplo, int n, double alpha, double[] x, int xIdx, int incx, double[] y, int yIdx, int incy, double[] ap, int apIdx);
+ public static native void dspr(char uplo, int n, double alpha, double[] x, int xIdx, int incx, double[] ap, int apIdx);
+ public static native void dswap(int n, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy);
+ public static native void dsymm(char side, char uplo, int m, int n, double alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb, double beta, double[] c, int cIdx, int ldc);
+ public static native void dsymv(char uplo, int n, double alpha, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx, double beta, double[] y, int yIdx, int incy);
+ public static native void dsyr2(char uplo, int n, double alpha, double[] x, int xIdx, int incx, double[] y, int yIdx, int incy, double[] a, int aIdx, int lda);
+ public static native void dsyr2k(char uplo, char trans, int n, int k, double alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb, double beta, double[] c, int cIdx, int ldc);
+ public static native void dsyr(char uplo, int n, double alpha, double[] x, int xIdx, int incx, double[] a, int aIdx, int lda);
+ public static native void dsyrk(char uplo, char trans, int n, int k, double alpha, double[] a, int aIdx, int lda, double beta, double[] c, int cIdx, int ldc);
+ public static native void dtbmv(char uplo, char trans, char diag, int n, int k, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx);
+ public static native void dtbsv(char uplo, char trans, char diag, int n, int k, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx);
+ public static native void dtpmv(char uplo, char trans, char diag, int n, double[] ap, int apIdx, double[] x, int xIdx, int incx);
+ public static native void dtpsv(char uplo, char trans, char diag, int n, double[] ap, int apIdx, double[] x, int xIdx, int incx);
+ public static native void dtrmm(char side, char uplo, char transa, char diag, int m, int n, double alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb);
+ public static native void dtrmv(char uplo, char trans, char diag, int n, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx);
+ public static native void dtrsm(char side, char uplo, char transa, char diag, int m, int n, double alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb);
+ public static native void dtrsv(char uplo, char trans, char diag, int n, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx);
+ public static native double dzasum(int n, double[] zx, int zxIdx, int incx);
+ public static native double dznrm2(int n, double[] x, int xIdx, int incx);
+ public static native int icamax(int n, float[] cx, int cxIdx, int incx);
+ public static native int idamax(int n, double[] dx, int dxIdx, int incx);
+ public static native int isamax(int n, float[] sx, int sxIdx, int incx);
+ public static native int izamax(int n, double[] zx, int zxIdx, int incx);
+ public static native int lsame(char ca, char cb);
+ public static native float sasum(int n, float[] sx, int sxIdx, int incx);
+ public static native void saxpy(int n, float sa, float[] sx, int sxIdx, int incx, float[] sy, int syIdx, int incy);
+ public static native float scasum(int n, float[] cx, int cxIdx, int incx);
+ public static native float scnrm2(int n, float[] x, int xIdx, int incx);
+ public static native void scopy(int n, float[] sx, int sxIdx, int incx, float[] sy, int syIdx, int incy);
+ public static native float sdot(int n, float[] sx, int sxIdx, int incx, float[] sy, int syIdx, int incy);
+ public static native float sdsdot(int n, float sb, float[] sx, int sxIdx, int incx, float[] sy, int syIdx, int incy);
+ public static native void sgbmv(char trans, int m, int n, int kl, int ku, float alpha, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx, float beta, float[] y, int yIdx, int incy);
+ public static native void sgemm(char transa, char transb, int m, int n, int k, float alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb, float beta, float[] c, int cIdx, int ldc);
+ public static native void sgemv(char trans, int m, int n, float alpha, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx, float beta, float[] y, int yIdx, int incy);
+ public static native void sger(int m, int n, float alpha, float[] x, int xIdx, int incx, float[] y, int yIdx, int incy, float[] a, int aIdx, int lda);
+ public static native float snrm2(int n, float[] x, int xIdx, int incx);
+ public static native void srot(int n, float[] sx, int sxIdx, int incx, float[] sy, int syIdx, int incy, float c, float s);
+ public static native void srotg(float sa, float sb, float c, float s);
+ public static native void srotm(int n, float[] sx, int sxIdx, int incx, float[] sy, int syIdx, int incy, float[] sparam, int sparamIdx);
+ public static native void srotmg(float[] sd1, int sd1Idx, float[] sd2, int sd2Idx, float[] sx1, int sx1Idx, float sy1, float[] sparam, int sparamIdx);
+ public static native void ssbmv(char uplo, int n, int k, float alpha, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx, float beta, float[] y, int yIdx, int incy);
+ public static native void sscal(int n, float sa, float[] sx, int sxIdx, int incx);
+ public static native void sspmv(char uplo, int n, float alpha, float[] ap, int apIdx, float[] x, int xIdx, int incx, float beta, float[] y, int yIdx, int incy);
+ public static native void sspr2(char uplo, int n, float alpha, float[] x, int xIdx, int incx, float[] y, int yIdx, int incy, float[] ap, int apIdx);
+ public static native void sspr(char uplo, int n, float alpha, float[] x, int xIdx, int incx, float[] ap, int apIdx);
+ public static native void sswap(int n, float[] sx, int sxIdx, int incx, float[] sy, int syIdx, int incy);
+ public static native void ssymm(char side, char uplo, int m, int n, float alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb, float beta, float[] c, int cIdx, int ldc);
+ public static native void ssymv(char uplo, int n, float alpha, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx, float beta, float[] y, int yIdx, int incy);
+ public static native void ssyr2(char uplo, int n, float alpha, float[] x, int xIdx, int incx, float[] y, int yIdx, int incy, float[] a, int aIdx, int lda);
+ public static native void ssyr2k(char uplo, char trans, int n, int k, float alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb, float beta, float[] c, int cIdx, int ldc);
+ public static native void ssyr(char uplo, int n, float alpha, float[] x, int xIdx, int incx, float[] a, int aIdx, int lda);
+ public static native void ssyrk(char uplo, char trans, int n, int k, float alpha, float[] a, int aIdx, int lda, float beta, float[] c, int cIdx, int ldc);
+ public static native void stbmv(char uplo, char trans, char diag, int n, int k, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx);
+ public static native void stbsv(char uplo, char trans, char diag, int n, int k, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx);
+ public static native void stpmv(char uplo, char trans, char diag, int n, float[] ap, int apIdx, float[] x, int xIdx, int incx);
+ public static native void stpsv(char uplo, char trans, char diag, int n, float[] ap, int apIdx, float[] x, int xIdx, int incx);
+ public static native void strmm(char side, char uplo, char transa, char diag, int m, int n, float alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb);
+ public static native void strmv(char uplo, char trans, char diag, int n, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx);
+ public static native void strsm(char side, char uplo, char transa, char diag, int m, int n, float alpha, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb);
+ public static native void strsv(char uplo, char trans, char diag, int n, float[] a, int aIdx, int lda, float[] x, int xIdx, int incx);
+ public static native void zaxpy(int n, ComplexDouble za, double[] zx, int zxIdx, int incx, double[] zy, int zyIdx, int incy);
+ public static native void zcopy(int n, double[] zx, int zxIdx, int incx, double[] zy, int zyIdx, int incy);
+ public static native ComplexDouble zdotc(int n, double[] zx, int zxIdx, int incx, double[] zy, int zyIdx, int incy);
+ public static native ComplexDouble zdotu(int n, double[] zx, int zxIdx, int incx, double[] zy, int zyIdx, int incy);
+ public static native void zdrot(int n, double[] cx, int cxIdx, int incx, double[] cy, int cyIdx, int incy, double c, double s);
+ public static native void zdscal(int n, double da, double[] zx, int zxIdx, int incx);
+ public static native void zgbmv(char trans, int m, int n, int kl, int ku, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx, ComplexDouble beta, double[] y, int yIdx, int incy);
+ public static native void zgemm(char transa, char transb, int m, int n, int k, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb, ComplexDouble beta, double[] c, int cIdx, int ldc);
+ public static native void zgemv(char trans, int m, int n, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx, ComplexDouble beta, double[] y, int yIdx, int incy);
+ public static native void zgerc(int m, int n, ComplexDouble alpha, double[] x, int xIdx, int incx, double[] y, int yIdx, int incy, double[] a, int aIdx, int lda);
+ public static native void zgeru(int m, int n, ComplexDouble alpha, double[] x, int xIdx, int incx, double[] y, int yIdx, int incy, double[] a, int aIdx, int lda);
+ public static native void zhbmv(char uplo, int n, int k, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx, ComplexDouble beta, double[] y, int yIdx, int incy);
+ public static native void zhemm(char side, char uplo, int m, int n, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb, ComplexDouble beta, double[] c, int cIdx, int ldc);
+ public static native void zhemv(char uplo, int n, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx, ComplexDouble beta, double[] y, int yIdx, int incy);
+ public static native void zher2(char uplo, int n, ComplexDouble alpha, double[] x, int xIdx, int incx, double[] y, int yIdx, int incy, double[] a, int aIdx, int lda);
+ public static native void zher2k(char uplo, char trans, int n, int k, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb, double beta, double[] c, int cIdx, int ldc);
+ public static native void zher(char uplo, int n, double alpha, double[] x, int xIdx, int incx, double[] a, int aIdx, int lda);
+ public static native void zherk(char uplo, char trans, int n, int k, double alpha, double[] a, int aIdx, int lda, double beta, double[] c, int cIdx, int ldc);
+ public static native void zhpmv(char uplo, int n, ComplexDouble alpha, double[] ap, int apIdx, double[] x, int xIdx, int incx, ComplexDouble beta, double[] y, int yIdx, int incy);
+ public static native void zhpr2(char uplo, int n, ComplexDouble alpha, double[] x, int xIdx, int incx, double[] y, int yIdx, int incy, double[] ap, int apIdx);
+ public static native void zhpr(char uplo, int n, double alpha, double[] x, int xIdx, int incx, double[] ap, int apIdx);
+ public static native void zrotg(ComplexDouble ca, ComplexDouble cb, double c, ComplexDouble s);
+ public static native void zscal(int n, ComplexDouble za, double[] zx, int zxIdx, int incx);
+ public static native void zswap(int n, double[] zx, int zxIdx, int incx, double[] zy, int zyIdx, int incy);
+ public static native void zsymm(char side, char uplo, int m, int n, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb, ComplexDouble beta, double[] c, int cIdx, int ldc);
+ public static native void zsyr2k(char uplo, char trans, int n, int k, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb, ComplexDouble beta, double[] c, int cIdx, int ldc);
+ public static native void zsyrk(char uplo, char trans, int n, int k, ComplexDouble alpha, double[] a, int aIdx, int lda, ComplexDouble beta, double[] c, int cIdx, int ldc);
+ public static native void ztbmv(char uplo, char trans, char diag, int n, int k, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx);
+ public static native void ztbsv(char uplo, char trans, char diag, int n, int k, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx);
+ public static native void ztpmv(char uplo, char trans, char diag, int n, double[] ap, int apIdx, double[] x, int xIdx, int incx);
+ public static native void ztpsv(char uplo, char trans, char diag, int n, double[] ap, int apIdx, double[] x, int xIdx, int incx);
+ public static native void ztrmm(char side, char uplo, char transa, char diag, int m, int n, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb);
+ public static native void ztrmv(char uplo, char trans, char diag, int n, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx);
+ public static native void ztrsm(char side, char uplo, char transa, char diag, int m, int n, ComplexDouble alpha, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb);
+ public static native void ztrsv(char uplo, char trans, char diag, int n, double[] a, int aIdx, int lda, double[] x, int xIdx, int incx);
+ public static native int dgesv(int n, int nrhs, double[] a, int aIdx, int lda, int[] ipiv, int ipivIdx, double[] b, int bIdx, int ldb);
+ public static native int sgesv(int n, int nrhs, float[] a, int aIdx, int lda, int[] ipiv, int ipivIdx, float[] b, int bIdx, int ldb);
+ public static native int dsysv(char uplo, int n, int nrhs, double[] a, int aIdx, int lda, int[] ipiv, int ipivIdx, double[] b, int bIdx, int ldb, double[] work, int workIdx, int lwork);
+ public static int dsysv(char uplo, int n, int nrhs, double[] a, int aIdx, int lda, int[] ipiv, int ipivIdx, double[] b, int bIdx, int ldb) {
+ int info;
+ double[] work = new double[1];
+ int lwork;
+ info = dsysv(uplo, n, nrhs, a, aIdx, lda, ipiv, ipivIdx, b, bIdx, ldb, work, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new double[lwork];
+ info = dsysv(uplo, n, nrhs, a, aIdx, lda, ipiv, ipivIdx, b, bIdx, ldb, work, 0, lwork);
+ return info;
+ }
+
+ public static native int ssysv(char uplo, int n, int nrhs, float[] a, int aIdx, int lda, int[] ipiv, int ipivIdx, float[] b, int bIdx, int ldb, float[] work, int workIdx, int lwork);
+ public static int ssysv(char uplo, int n, int nrhs, float[] a, int aIdx, int lda, int[] ipiv, int ipivIdx, float[] b, int bIdx, int ldb) {
+ int info;
+ float[] work = new float[1];
+ int lwork;
+ info = ssysv(uplo, n, nrhs, a, aIdx, lda, ipiv, ipivIdx, b, bIdx, ldb, work, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new float[lwork];
+ info = ssysv(uplo, n, nrhs, a, aIdx, lda, ipiv, ipivIdx, b, bIdx, ldb, work, 0, lwork);
+ return info;
+ }
+
+ public static native int dsyev(char jobz, char uplo, int n, double[] a, int aIdx, int lda, double[] w, int wIdx, double[] work, int workIdx, int lwork);
+ public static int dsyev(char jobz, char uplo, int n, double[] a, int aIdx, int lda, double[] w, int wIdx) {
+ int info;
+ double[] work = new double[1];
+ int lwork;
+ info = dsyev(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new double[lwork];
+ info = dsyev(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, lwork);
+ return info;
+ }
+
+ public static native int ssyev(char jobz, char uplo, int n, float[] a, int aIdx, int lda, float[] w, int wIdx, float[] work, int workIdx, int lwork);
+ public static int ssyev(char jobz, char uplo, int n, float[] a, int aIdx, int lda, float[] w, int wIdx) {
+ int info;
+ float[] work = new float[1];
+ int lwork;
+ info = ssyev(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new float[lwork];
+ info = ssyev(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, lwork);
+ return info;
+ }
+
+ public static native int dsyevd(char jobz, char uplo, int n, double[] a, int aIdx, int lda, double[] w, int wIdx, double[] work, int workIdx, int lwork, int[] iwork, int iworkIdx, int liwork);
+ public static int dsyevd(char jobz, char uplo, int n, double[] a, int aIdx, int lda, double[] w, int wIdx) {
+ int info;
+ double[] work = new double[1];
+ int lwork;
+ int[] iwork = new int[1];
+ int liwork;
+ info = dsyevd(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, -1, iwork, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new double[lwork];
+ liwork = (int) iwork[0]; iwork = new int[liwork];
+ info = dsyevd(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, lwork, iwork, 0, liwork);
+ return info;
+ }
+
+ public static native int dsyevr(char jobz, char range, char uplo, int n, double[] a, int aIdx, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, int mIdx, double[] w, int wIdx, double[] z, int zIdx, int ldz, int[] isuppz, int isuppzIdx, double[] work, int workIdx, int lwork, int[] iwork, int iworkIdx, int liwork);
+ public static int dsyevr(char jobz, char range, char uplo, int n, double[] a, int aIdx, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, int mIdx, double[] w, int wIdx, double[] z, int zIdx, int ldz, int[] isuppz, int isuppzIdx) {
+ int info;
+ double[] work = new double[1];
+ int lwork;
+ int[] iwork = new int[1];
+ int liwork;
+ info = dsyevr(jobz, range, uplo, n, a, aIdx, lda, vl, vu, il, iu, abstol, m, mIdx, w, wIdx, z, zIdx, ldz, isuppz, isuppzIdx, work, 0, -1, iwork, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new double[lwork];
+ liwork = (int) iwork[0]; iwork = new int[liwork];
+ info = dsyevr(jobz, range, uplo, n, a, aIdx, lda, vl, vu, il, iu, abstol, m, mIdx, w, wIdx, z, zIdx, ldz, isuppz, isuppzIdx, work, 0, lwork, iwork, 0, liwork);
+ return info;
+ }
+
+ public static native int dsyevx(char jobz, char range, char uplo, int n, double[] a, int aIdx, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, int mIdx, double[] w, int wIdx, double[] z, int zIdx, int ldz, double[] work, int workIdx, int lwork, int[] iwork, int iworkIdx, int[] ifail, int ifailIdx);
+ public static int dsyevx(char jobz, char range, char uplo, int n, double[] a, int aIdx, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, int mIdx, double[] w, int wIdx, double[] z, int zIdx, int ldz, int[] iwork, int iworkIdx, int[] ifail, int ifailIdx) {
+ int info;
+ double[] work = new double[1];
+ int lwork;
+ info = dsyevx(jobz, range, uplo, n, a, aIdx, lda, vl, vu, il, iu, abstol, m, mIdx, w, wIdx, z, zIdx, ldz, work, 0, -1, iwork, iworkIdx, ifail, ifailIdx);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new double[lwork];
+ info = dsyevx(jobz, range, uplo, n, a, aIdx, lda, vl, vu, il, iu, abstol, m, mIdx, w, wIdx, z, zIdx, ldz, work, 0, lwork, iwork, iworkIdx, ifail, ifailIdx);
+ return info;
+ }
+
+ public static native int ssyevd(char jobz, char uplo, int n, float[] a, int aIdx, int lda, float[] w, int wIdx, float[] work, int workIdx, int lwork, int[] iwork, int iworkIdx, int liwork);
+ public static int ssyevd(char jobz, char uplo, int n, float[] a, int aIdx, int lda, float[] w, int wIdx) {
+ int info;
+ float[] work = new float[1];
+ int lwork;
+ int[] iwork = new int[1];
+ int liwork;
+ info = ssyevd(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, -1, iwork, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new float[lwork];
+ liwork = (int) iwork[0]; iwork = new int[liwork];
+ info = ssyevd(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, lwork, iwork, 0, liwork);
+ return info;
+ }
+
+ public static native int ssyevr(char jobz, char range, char uplo, int n, float[] a, int aIdx, int lda, float vl, float vu, int il, int iu, float abstol, int[] m, int mIdx, float[] w, int wIdx, float[] z, int zIdx, int ldz, int[] isuppz, int isuppzIdx, float[] work, int workIdx, int lwork, int[] iwork, int iworkIdx, int liwork);
+ public static int ssyevr(char jobz, char range, char uplo, int n, float[] a, int aIdx, int lda, float vl, float vu, int il, int iu, float abstol, int[] m, int mIdx, float[] w, int wIdx, float[] z, int zIdx, int ldz, int[] isuppz, int isuppzIdx) {
+ int info;
+ float[] work = new float[1];
+ int lwork;
+ int[] iwork = new int[1];
+ int liwork;
+ info = ssyevr(jobz, range, uplo, n, a, aIdx, lda, vl, vu, il, iu, abstol, m, mIdx, w, wIdx, z, zIdx, ldz, isuppz, isuppzIdx, work, 0, -1, iwork, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new float[lwork];
+ liwork = (int) iwork[0]; iwork = new int[liwork];
+ info = ssyevr(jobz, range, uplo, n, a, aIdx, lda, vl, vu, il, iu, abstol, m, mIdx, w, wIdx, z, zIdx, ldz, isuppz, isuppzIdx, work, 0, lwork, iwork, 0, liwork);
+ return info;
+ }
+
+ public static native int ssyevx(char jobz, char range, char uplo, int n, float[] a, int aIdx, int lda, float vl, float vu, int il, int iu, float abstol, int[] m, int mIdx, float[] w, int wIdx, float[] z, int zIdx, int ldz, float[] work, int workIdx, int lwork, int[] iwork, int iworkIdx, int[] ifail, int ifailIdx);
+ public static int ssyevx(char jobz, char range, char uplo, int n, float[] a, int aIdx, int lda, float vl, float vu, int il, int iu, float abstol, int[] m, int mIdx, float[] w, int wIdx, float[] z, int zIdx, int ldz, int[] iwork, int iworkIdx, int[] ifail, int ifailIdx) {
+ int info;
+ float[] work = new float[1];
+ int lwork;
+ info = ssyevx(jobz, range, uplo, n, a, aIdx, lda, vl, vu, il, iu, abstol, m, mIdx, w, wIdx, z, zIdx, ldz, work, 0, -1, iwork, iworkIdx, ifail, ifailIdx);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new float[lwork];
+ info = ssyevx(jobz, range, uplo, n, a, aIdx, lda, vl, vu, il, iu, abstol, m, mIdx, w, wIdx, z, zIdx, ldz, work, 0, lwork, iwork, iworkIdx, ifail, ifailIdx);
+ return info;
+ }
+
+ public static native int dposv(char uplo, int n, int nrhs, double[] a, int aIdx, int lda, double[] b, int bIdx, int ldb);
+ public static native int sposv(char uplo, int n, int nrhs, float[] a, int aIdx, int lda, float[] b, int bIdx, int ldb);
+ public static native int dgeev(char jobvl, char jobvr, int n, double[] a, int aIdx, int lda, double[] wr, int wrIdx, double[] wi, int wiIdx, double[] vl, int vlIdx, int ldvl, double[] vr, int vrIdx, int ldvr, double[] work, int workIdx, int lwork);
+ public static int dgeev(char jobvl, char jobvr, int n, double[] a, int aIdx, int lda, double[] wr, int wrIdx, double[] wi, int wiIdx, double[] vl, int vlIdx, int ldvl, double[] vr, int vrIdx, int ldvr) {
+ int info;
+ double[] work = new double[1];
+ int lwork;
+ info = dgeev(jobvl, jobvr, n, a, aIdx, lda, wr, wrIdx, wi, wiIdx, vl, vlIdx, ldvl, vr, vrIdx, ldvr, work, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new double[lwork];
+ info = dgeev(jobvl, jobvr, n, a, aIdx, lda, wr, wrIdx, wi, wiIdx, vl, vlIdx, ldvl, vr, vrIdx, ldvr, work, 0, lwork);
+ return info;
+ }
+
+ public static native int sgeev(char jobvl, char jobvr, int n, float[] a, int aIdx, int lda, float[] wr, int wrIdx, float[] wi, int wiIdx, float[] vl, int vlIdx, int ldvl, float[] vr, int vrIdx, int ldvr, float[] work, int workIdx, int lwork);
+ public static int sgeev(char jobvl, char jobvr, int n, float[] a, int aIdx, int lda, float[] wr, int wrIdx, float[] wi, int wiIdx, float[] vl, int vlIdx, int ldvl, float[] vr, int vrIdx, int ldvr) {
+ int info;
+ float[] work = new float[1];
+ int lwork;
+ info = sgeev(jobvl, jobvr, n, a, aIdx, lda, wr, wrIdx, wi, wiIdx, vl, vlIdx, ldvl, vr, vrIdx, ldvr, work, 0, -1);
+ if (info != 0)
+ return info;
+ lwork = (int) work[0]; work = new float[lwork];
+ info = sgeev(jobvl, jobvr, n, a, aIdx, lda, wr, wrIdx, wi, wiIdx, vl, vlIdx, ldvl, vr, vrIdx, ldvr, work, 0, lwork);
+ return info;
+ }
+
+
+}
diff --git a/src/org/jblas/la/ComplexDoubleMatrix.java b/src/org/jblas/la/ComplexDoubleMatrix.java
new file mode 100644
index 0000000..f44a292
--- /dev/null
+++ b/src/org/jblas/la/ComplexDoubleMatrix.java
@@ -0,0 +1,2011 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.exceptions.SizeException;
+import org.jblas.core.ComplexDouble;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class ComplexDoubleMatrix {
+
+ public int rows;
+ public int columns;
+ public int length;
+ public double[] data = null; // rows are contiguous
+
+ /**************************************************************************
+ *
+ * Constructors and factory functions
+ *
+ **************************************************************************/
+
+ /** Create a new matrix with <i>newRows</i> rows, <i>newColumns</i> columns
+ * using <i>newData></i> as the data. The length of the data is not checked!
+ */
+ public ComplexDoubleMatrix(int newRows, int newColumns, double... newData) {
+ rows = newRows;
+ columns = newColumns;
+ length = rows * columns;
+
+ if (newData.length != 2 * newRows * newColumns)
+ throw new IllegalArgumentException(
+ "Passed data must match matrix dimensions.");
+
+ data = newData;
+ }
+
+ /**
+ * Creates a new <i>n</i> times <i>m</i> <tt>ComplexDoubleMatrix</tt>.
+ * @param newRows the number of rows (<i>n</i>) of the new matrix.
+ * @param newColumns the number of columns (<i>m</i>) of the new matrix.
+ */
+ public ComplexDoubleMatrix(int newRows, int newColumns) {
+ this(newRows, newColumns, new double[2 * newRows * newColumns]);
+ }
+
+ /**
+ * Creates a new <tt>ComplexDoubleMatrix</tt> of size 0 times 0.
+ */
+ public ComplexDoubleMatrix() {
+ this(0, 0, null);
+ }
+
+ /**
+ * Create a Matrix of length <tt>len</tt>. By default, this creates a row vector.
+ * @param len
+ */
+ public ComplexDoubleMatrix(int len) {
+ this(len, 1, new double[2 * len]);
+ }
+
+ public ComplexDoubleMatrix(double[] newData) {
+ this(newData.length/2);
+
+ data = newData;
+ }
+
+ public ComplexDoubleMatrix(ComplexDouble[] newData) {
+ this(newData.length);
+
+ for (int i = 0; i < newData.length; i++)
+ put(i, newData[i]);
+ }
+
+
+ /** Construct a complex matrix from a real matrix. */
+ public ComplexDoubleMatrix(DoubleMatrix m) {
+ this(m.rows, m.columns);
+
+ Blas.dcopy(m.length, m.data, 0, 1, data, 0, 2);
+ }
+
+ /** Construct a complex matrix from separate real and imaginary parts. Either
+ * part can be set to null in which case it will be ignored.
+ */
+ public ComplexDoubleMatrix(DoubleMatrix real, DoubleMatrix imag) {
+ this(real.rows, real.columns);
+ real.assertSameSize(imag);
+
+ if (real != null)
+ Blas.dcopy(length, real.data, 0, 1, data, 0, 2);
+ if (imag != null)
+ Blas.dcopy(length, imag.data, 0, 1, data, 1, 2);
+ }
+
+ /**
+ * Creates a new matrix by reading it from a file.
+ * @param filename the path and name of the file to read the matrix from
+ * @throws IOException
+ */
+ public ComplexDoubleMatrix(String filename) throws IOException {
+ load(filename);
+ }
+
+ /**
+ * Creates a new <i>n</i> times <i>m</i> <tt>ComplexDoubleMatrix</tt> from
+ * the given <i>n</i> times <i>m</i> 2D data array. The first dimension of the array makes the
+ * rows (<i>n</i>) and the second dimension the columns (<i>m</i>). For example, the
+ * given code <br/><br/>
+ * <code>new ComplexDoubleMatrix(new double[][]{{1d, 2d, 3d}, {4d, 5d, 6d}, {7d, 8d, 9d}}).print();</code><br/><br/>
+ * will constructs the following matrix:
+ * <pre>
+ * 1.0 2.0 3.0
+ * 4.0 5.0 6.0
+ * 7.0 8.0 9.0
+ * </pre>.
+ * @param data <i>n</i> times <i>m</i> data array
+ */
+ public ComplexDoubleMatrix(double[][] data) {
+ this(data.length, data[0].length);
+
+ for (int r = 0; r < rows; r++)
+ assert(data[r].length == columns);
+
+ for (int r = 0; r < rows; r++)
+ for (int c = 0; c < columns; c++)
+ put(r, c, data[r][c]);
+ }
+
+ /**
+ * Creates a new matrix in which all values are equal 0.
+ * @param rows number of rows
+ * @param columns number of columns
+ * @return new matrix
+ */
+ public static ComplexDoubleMatrix zeros(int rows, int columns) {
+ return new ComplexDoubleMatrix(rows, columns);
+ }
+
+ public static ComplexDoubleMatrix zeros(int length) {
+ return zeros(length, 1);
+ }
+
+ /**
+ * Creates a new matrix in which all values are equal 1.
+ * @param rows number of rows
+ * @param columns number of columns
+ * @return new matrix
+ */
+ public static ComplexDoubleMatrix ones(int rows, int columns) {
+ ComplexDoubleMatrix m = new ComplexDoubleMatrix(rows, columns);
+
+ for (int i = 0; i < rows * columns; i++)
+ m.put(i, 1.0);
+
+ return m;
+ }
+
+ public static ComplexDoubleMatrix ones(int length) {
+ return ones(length, 1);
+ }
+
+ /**
+ * Creates a new matrix where the values of the given vector are the diagonal values of
+ * the matrix.
+ * @param x the diagonal values
+ * @return new matrix
+ */
+ public static ComplexDoubleMatrix diag(ComplexDoubleMatrix x) {
+ ComplexDoubleMatrix m = new ComplexDoubleMatrix(x.length, x.length);
+
+ for (int i = 0; i < x.length; i++)
+ m.put(i, i, x.get(i));
+
+ return m;
+ }
+
+ /**
+ * Create a 1 * 1 - matrix. For many operations, this matrix functions like a
+ * normal double
+ * @param s value of the matrix
+ * @return the constructed ComplexDoubleMatrix
+ */
+ public static ComplexDoubleMatrix scalar(double s) {
+ ComplexDoubleMatrix m = new ComplexDoubleMatrix(1, 1);
+ m.put(0, 0, s);
+ return m;
+ }
+
+ /** Test whether a matrix is scalar */
+ public boolean isScalar() {
+ return length == 1;
+ }
+
+ /** Return the first element of the matrix */
+ public ComplexDouble scalar() {
+ return get(0);
+ }
+
+ public static ComplexDoubleMatrix concatHorizontally(ComplexDoubleMatrix A, ComplexDoubleMatrix B) {
+ if (A.rows != B.rows)
+ throw new SizeException("Matrices don't have same number of rows.");
+
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(A.rows, A.columns + B.columns);
+ SimpleBlas.copy(A, result);
+ Blas.zcopy(B.length, B.data, 0, 1, result.data, A.length, 1);
+ return result;
+ }
+
+ public static ComplexDoubleMatrix concatVertically(ComplexDoubleMatrix A, ComplexDoubleMatrix B) {
+ if (A.columns != B.columns)
+ throw new SizeException("Matrices don't have same number of columns.");
+
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(A.rows + B.rows, A.columns);
+
+ for (int i = 0; i < A.columns; i++) {
+ Blas.zcopy(A.rows, A.data, A.index(0, i), 1, result.data, result.index(0, i), 1);
+ Blas.zcopy(B.rows, B.data, B.index(0, i), 1, result.data, result.index(A.rows, i), 1);
+ }
+
+ return result;
+ }
+
+ /**************************************************************************
+ * Working with slices (Man! 30+ methods just to make this a bit flexible...)
+ */
+
+ public ComplexDoubleMatrix get(int[] indices) {
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ result.put(i, get(indices[i]));
+
+ return result;
+ }
+
+ public ComplexDoubleMatrix get(int r, int[] indices) {
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(1, indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ result.put(i, get(r, indices[i]));
+
+ return result;
+ }
+
+ public ComplexDoubleMatrix get(int[] indices, int c) {
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(indices.length, c);
+
+ for (int i = 0; i < indices.length; i++)
+ result.put(i, get(indices[i], c));
+
+ return result;
+ }
+
+ public ComplexDoubleMatrix get(int[] rindices, int[] cindices) {
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(rindices.length, cindices.length);
+
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ result.put(i, j, get(rindices[i], cindices[j]));
+
+ return result;
+ }
+
+ public ComplexDoubleMatrix get(ComplexDoubleMatrix indices) {
+ return get(indices.findIndices());
+ }
+
+ public ComplexDoubleMatrix get(int r, ComplexDoubleMatrix indices) {
+ return get(r, indices.findIndices());
+ }
+
+ public ComplexDoubleMatrix get(ComplexDoubleMatrix indices, int c) {
+ return get(indices.findIndices(), c);
+ }
+
+ public ComplexDoubleMatrix get(ComplexDoubleMatrix rindices, ComplexDoubleMatrix cindices) {
+ return get(rindices.findIndices(), cindices.findIndices());
+ }
+
+ private void checkLength(int l) {
+ if (length != l)
+ throw new SizeException("Matrix does not have the necessary length (" + length + " != " + l + ").");
+ }
+
+ private void checkRows(int r) {
+ if (rows != r)
+ throw new SizeException("Matrix does not have the necessary length (" + length + " != " + r + ").");
+ }
+
+ private void checkColumns(int c) {
+ if (columns != c)
+ throw new SizeException("Matrix does not have the necessary length (" + length + " != " + c + ").");
+ }
+
+ public ComplexDoubleMatrix put(int[] indices, ComplexDoubleMatrix x) {
+ if (x.isScalar())
+ return put(indices, x.scalar());
+ x.checkLength(indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], x.get(i));
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int r, int[] indices, ComplexDoubleMatrix x) {
+ if (x.isScalar())
+ return put(r, indices, x.scalar());
+ x.checkColumns(indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ put(r, indices[i], x.get(i));
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int[] indices, int c, ComplexDoubleMatrix x) {
+ if (x.isScalar())
+ return put(indices, c, x.scalar());
+ x.checkRows(indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], c, x.get(i));
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int[] rindices, int[] cindices, ComplexDoubleMatrix x) {
+ if (x.isScalar())
+ return put(rindices, cindices, x.scalar());
+ x.checkRows(rindices.length);
+ x.checkColumns(cindices.length);
+
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ put(rindices[i], cindices[j], x.get(i,j));
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int[] indices, double v) {
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix putReal(int[] indices, double v) {
+ return put(indices, v);
+ }
+
+ public ComplexDoubleMatrix putImag(int[] indices, double v) {
+ for (int i = 0; i < indices.length; i++)
+ putImag(indices[i], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int[] indices, ComplexDouble v) {
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int r, int[] indices, double v) {
+ for (int i = 0; i < indices.length; i++)
+ put(r, indices[i], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix putReal(int r, int[] indices, double v) {
+ return put(r, indices, v);
+ }
+
+ public ComplexDoubleMatrix putImag(int r, int[] indices, double v) {
+ for (int i = 0; i < indices.length; i++)
+ putImag(r, indices[i], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int r, int[] indices, ComplexDouble v) {
+ for (int i = 0; i < indices.length; i++)
+ put(r, indices[i], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int[] indices, int c, double v) {
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], c, v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix putReal(int[] indices, int c, double v) {
+ return put(indices, c, v);
+ }
+
+ public ComplexDoubleMatrix putImag(int[] indices, int c, double v) {
+ for (int i = 0; i < indices.length; i++)
+ putImag(indices[i], c, v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int[] indices, int c, ComplexDouble v) {
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], c, v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int[] rindices, int[] cindices, double v) {
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ put(rindices[i], cindices[j], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix putReal(int[] rindices, int[] cindices, double v) {
+ return put(rindices, cindices, v);
+ }
+
+ public ComplexDoubleMatrix putImag(int[] rindices, int[] cindices, double v) {
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ put(rindices[i], cindices[j], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int[] rindices, int[] cindices, ComplexDouble v) {
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ put(rindices[i], cindices[j], v);
+
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix indices, ComplexDoubleMatrix v) {
+ return put(indices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix put(int r, ComplexDoubleMatrix indices, ComplexDoubleMatrix v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix indices, int c, ComplexDoubleMatrix v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix rindices, ComplexDoubleMatrix cindices, ComplexDoubleMatrix v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix indices, double v) {
+ return put(indices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix putReal(ComplexDoubleMatrix indices, double v) {
+ return put(indices, v);
+ }
+
+ public ComplexDoubleMatrix putImag(ComplexDoubleMatrix indices, double v) {
+ return putImag(indices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix indices, ComplexDouble v) {
+ return put(indices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix put(int r, ComplexDoubleMatrix indices, double v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix putReal(int r, ComplexDoubleMatrix indices, double v) {
+ return put(r, indices, v);
+ }
+
+ public ComplexDoubleMatrix putImag(int r, ComplexDoubleMatrix indices, double v) {
+ return putImag(r, indices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix put(int r, ComplexDoubleMatrix indices, ComplexDouble v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix indices, int c, double v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ public ComplexDoubleMatrix putReal(ComplexDoubleMatrix indices, int c, double v) {
+ return put(indices, c, v);
+ }
+
+ public ComplexDoubleMatrix putImag(ComplexDoubleMatrix indices, int c, double v) {
+ return putImag(indices.findIndices(), c, v);
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix indices, int c, ComplexDouble v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix rindices, ComplexDoubleMatrix cindices, double v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix putReal(ComplexDoubleMatrix rindices, ComplexDoubleMatrix cindices, double v) {
+ return putReal(rindices, cindices, v);
+ }
+
+ public ComplexDoubleMatrix putImag(ComplexDoubleMatrix rindices, ComplexDoubleMatrix cindices, double v) {
+ return putImag(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ public ComplexDoubleMatrix put(ComplexDoubleMatrix rindices, ComplexDoubleMatrix cindices, ComplexDouble v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+
+ public int[] findIndices() {
+ int len = 0;
+ for (int i = 0; i < length; i++)
+ if (!get(i).isZero())
+ len++;
+
+ int[] indices = new int[len];
+ int c = 0;
+
+ for (int i = 0; i < length; i++)
+ if (!get(i).isZero())
+ indices[c++] = i;
+
+ return indices;
+ }
+
+ /**************************************************************************
+ * Basic operations (copying, resizing, element access)
+ */
+
+ /** Return transposed copy of this matrix */
+ public ComplexDoubleMatrix transpose() {
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(columns, rows);
+
+ for (int i = 0; i < rows; i++)
+ for (int j = 0; j < columns; j++)
+ result.put(j, i, get(i, j));
+
+ return result;
+ }
+
+
+ /** Compare two matrices.
+ * @param o Object to compare to
+ * @return true if and only if other is also a ComplexDoubleMatrix which has the same size and the
+ * maximal absolute difference in matrix elements is smaller thatn 1e-6. */
+ public boolean equals(Object o) {
+ if (!(o instanceof ComplexDoubleMatrix))
+ return false;
+
+ ComplexDoubleMatrix other = (ComplexDoubleMatrix) o;
+
+ if (!sameSize(other))
+ return false;
+
+ DoubleMatrix diff = MatrixFunctions.absi(sub(other)).getReal();
+
+ return diff.max() / (rows * columns) < 1e-6;
+ }
+
+
+ /** Resize the matrix. All elements will be set to zero. */
+ public void resize(int newRows, int newColumns) {
+ rows = newRows;
+ columns = newColumns;
+ length = newRows * newColumns;
+ data = new double[2 * rows * columns];
+ }
+
+
+ /** Reshape the matrix. Number of elements must not change. */
+ public ComplexDoubleMatrix reshape(int newRows, int newColumns) {
+ if (length != newRows * newColumns)
+ throw new IllegalArgumentException(
+ "Number of elements must not change.");
+
+ rows = newRows;
+ columns = newColumns;
+
+ return this;
+ }
+
+ /** Checks whether two matrices have the same size. */
+ public boolean sameSize(ComplexDoubleMatrix a) {
+ return rows == a.rows && columns == a.columns;
+ }
+
+ /**
+ * Assert that two matrices have the same size.
+ *
+ * @param a the other matrix
+ * @throws SizeException if matrix sizes don't match.
+ * */
+ public void assertSameSize(ComplexDoubleMatrix a) {
+ if (!sameSize(a))
+ throw new SizeException("Matrices must have the same size.");
+ }
+
+ /**
+ * Check whether this can be multiplied with a.
+ *
+ * @param a right-hand-side of the multiplication.
+ * @return true iff <tt>this.columns == a.rows</tt>
+ */
+ public boolean multipliesWith(ComplexDoubleMatrix a) {
+ return columns == a.rows;
+ }
+
+ public void assertMultipliesWith(ComplexDoubleMatrix a) {
+ if (!multipliesWith(a))
+ throw new SizeException("Number of columns of left matrix must be equal to number of rows of right matrix.");
+ }
+
+ public boolean sameLength(ComplexDoubleMatrix a) {
+ return length == a.length;
+ }
+
+ public void assertSameLength(ComplexDoubleMatrix a) {
+ if (!sameLength(a))
+ throw new SizeException("Matrices must have same length (is: " + length + " and " + a.length + ")");
+ }
+
+ /** Copy ComplexDoubleMatrix a to this. this a is resized if necessary. */
+ public ComplexDoubleMatrix copy(ComplexDoubleMatrix a) {
+ if (!sameSize(a))
+ resize(a.rows, a.columns);
+
+ SimpleBlas.copy(a, this);
+ return a;
+ }
+
+ /** Returns a duplicate of this matrix. Geometry is the same (including offsets, transpose, etc.),
+ * but the buffer is not shared.
+ */
+ public ComplexDoubleMatrix dup() {
+ ComplexDoubleMatrix out = new ComplexDoubleMatrix(rows, columns);
+
+ System.arraycopy(out.data, 0, data, 0, 2 * length);
+
+ return out;
+ }
+
+ public ComplexDoubleMatrix swapColumns(int i, int j) {
+ Blas.zswap(rows, data, index(0, i), 1, data, index(0, j), 1);
+ return this;
+ }
+
+ public ComplexDoubleMatrix swapRows(int i, int j) {
+ Blas.zswap(columns, data, index(i, 0), rows, data, index(j, 0), rows);
+ return this;
+ }
+
+ /** Set matrix element */
+ public ComplexDoubleMatrix put(int rowIndex, int columnIndex, double value) {
+ data[2*index(rowIndex, columnIndex)] = value;
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int rowIndex, int columnIndex, ComplexDouble value) {
+ int i = 2*index(rowIndex, columnIndex);
+ data[i] = value.real(); data[i+1] = value.imag();
+ return this;
+ }
+
+ public ComplexDoubleMatrix putReal(int rowIndex, int columnIndex, double value) {
+ data[2*index(rowIndex, columnIndex)] = value;
+ return this;
+ }
+
+ public ComplexDoubleMatrix putImag(int rowIndex, int columnIndex, double value) {
+ data[2*index(rowIndex, columnIndex)+1] = value;
+ return this;
+ }
+
+ /** Retrieve matrix element */
+ public ComplexDouble get(int rowIndex, int columnIndex) {
+ int i = 2*index(rowIndex, columnIndex);
+ return new ComplexDouble(data[i], data[i+1]);
+ }
+
+ public DoubleMatrix getReal() {
+ DoubleMatrix result = new DoubleMatrix(rows, columns);
+
+ Blas.dcopy(length, data, 0, 2, result.data, 0, 1);
+
+ return result;
+ }
+
+ /** Get index of an element */
+ public int index(int rowIndex, int columnIndex) {
+ //System.out.printf("Index for (%d, %d) -> %d\n", rowIndex, columnIndex, (rows * columnIndex + rowIndex) * 2);
+ return rows * columnIndex + rowIndex;
+ }
+
+ public ComplexDouble get(int i) {
+ return new ComplexDouble(data[i * 2], data[i * 2 + 1]);
+ }
+
+ public ComplexDouble get(int i, ComplexDouble result) {
+ return result.set(data[i * 2], data[i*2+1]);
+ }
+
+ public double getReal(int i) {
+ return data[2*i];
+ }
+
+ public double getImag(int i) {
+ return data[2*i + 1];
+ }
+
+ public ComplexDoubleMatrix put(int i, double v) {
+ data[2*i] = v;
+ return this;
+ }
+
+ public ComplexDoubleMatrix put(int i, ComplexDouble v) {
+ data[2*i] = v.real();
+ data[2*i+1] = v.imag();
+ return this;
+ }
+
+ public ComplexDoubleMatrix putReal(int i, double v) {
+ return put(i, v);
+ }
+
+ public ComplexDoubleMatrix putImag(int i, double v) {
+ data[2*i+1] = v;
+ return this;
+ }
+
+ public int getRows() {
+ return rows;
+ }
+
+ public int getColumns() {
+ return columns;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ /** Checks whether the matrix is empty. */
+ public boolean isEmpty() {
+ return columns == 0 || rows == 0;
+ }
+
+ /** Checks whether the matrix is square. */
+ public boolean isSquare() {
+ return columns == rows;
+ }
+
+ public void assertSquare() {
+ if (!isSquare())
+ throw new SizeException("Matrix must be square!");
+ }
+
+ /** Checks whether the matrix is a vector. */
+ public boolean isVector() {
+ return columns == 1 || rows == 1;
+ }
+
+ public boolean isRowVector() {
+ return columns == 1;
+ }
+
+ public boolean isColumnVector() {
+ return rows == 1;
+ }
+
+ /** Get diagonal of the matrix. */
+ public ComplexDoubleMatrix diag() {
+ ComplexDoubleMatrix d = new ComplexDoubleMatrix(rows);
+ Blas.zcopy(rows, data, 0, rows + 1, d.data, 0, 1);
+ return d;
+ }
+
+ /** Get real part of the matrix. */
+ public DoubleMatrix real() {
+ DoubleMatrix result = new DoubleMatrix(rows, columns);
+ Blas.dcopy(length, data, 0, 2, result.data, 0, 1);
+ return result;
+ }
+
+ /** Get imaginary part of the matrix. */
+ public DoubleMatrix imag() {
+ DoubleMatrix result = new DoubleMatrix(rows, columns);
+ Blas.dcopy(length, data, 1, 2, result.data, 0, 1);
+ return result;
+ }
+
+
+ /**
+ * Pretty-print this matrix to <tt>System.out</tt>.
+ * */
+ public void print() {
+ System.out.println(toString());
+ }
+
+ /**
+ * Generate string representation of this matrix
+ * (multi-line).
+ * */
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+
+ s.append("[");
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < columns; j++) {
+ s.append(get(i, j));
+ if (j < columns - 1)
+ s.append(", ");
+ }
+ if (i < rows - 1)
+ s.append("; ");
+ }
+
+ s.append("]");
+
+ return s.toString();
+ }
+
+ public double[] toDoubleArray() {
+ double[] array = new double[2*length];
+
+ for (int i = 0; i < 2*length; i++)
+ array[i] = data[i];
+
+ return array;
+ }
+
+ public ComplexDouble[] toArray() {
+ ComplexDouble[] array = new ComplexDouble[length];
+
+ for (int i = 0; i < length; i++)
+ array[i] = get(i);
+
+ return array;
+ }
+
+ public ComplexDouble[][] toArray2() {
+ ComplexDouble[][] array = new ComplexDouble[rows][columns];
+
+ for (int r = 0; r < rows; r++)
+ for (int c = 0; c < columns; c++)
+ array[r][c] = get(r, c);
+
+ return array;
+ }
+
+ public boolean[] toBooleanArray() {
+ boolean[] array = new boolean[length];
+
+ for (int i = 0; i < length; i++)
+ array[i] = get(i).isZero() ? false : true;
+
+ return array;
+ }
+
+ public boolean[][] toBooleanArray2() {
+ boolean[][] array = new boolean[rows][columns];
+
+ for (int r = 0; r < rows; r++)
+ for (int c = 0; c < columns; c++)
+ array[r][c] = get(r, c).isZero() ? false : true;
+
+ return array;
+ }
+
+ /**************************************************************************
+ * Arithmetic Operations
+ */
+
+ /**
+ * Ensures that the result vector has the same length as this. If not,
+ * resizing result is tried, which fails if result == this or result == other.
+ */
+ private void ensureResultLength(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (!sameLength(result)) {
+ if (result == this || result == other)
+ throw new SizeException("Cannot resize result matrix because it is used in-place.");
+ result.resize(rows, columns);
+ }
+ }
+
+ /** Add two matrices. */
+ public ComplexDoubleMatrix addi(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return addi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ if (result == this)
+ SimpleBlas.axpy(ComplexDouble.UNIT, other, result);
+ else if (result == other)
+ SimpleBlas.axpy(ComplexDouble.UNIT, this, result);
+ else {
+ SimpleBlas.copy(this, result);
+ SimpleBlas.axpy(ComplexDouble.UNIT, other, result);
+ }
+
+ return result;
+ }
+
+ /** Add a scalar to a matrix. */
+ public ComplexDoubleMatrix addi(ComplexDouble v, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i).add(v));
+ return result;
+ }
+
+ public ComplexDoubleMatrix addi(double v, ComplexDoubleMatrix result) {
+ return addi(new ComplexDouble(v), result);
+ }
+
+ /** Subtract two matrices. */
+ public ComplexDoubleMatrix subi(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return subi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ if (result == this)
+ SimpleBlas.axpy(ComplexDouble.NEG_UNIT, other, result);
+ else if (result == other) {
+ SimpleBlas.scal(ComplexDouble.NEG_UNIT, result);
+ SimpleBlas.axpy(ComplexDouble.UNIT, this, result);
+ }
+ else {
+ SimpleBlas.copy(this, result);
+ SimpleBlas.axpy(ComplexDouble.NEG_UNIT, other, result);
+ }
+ return result;
+ }
+
+ /** Subtract a scalar from a matrix */
+ public ComplexDoubleMatrix subi(ComplexDouble v, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i).sub(v));
+ return result;
+ }
+
+ public ComplexDoubleMatrix subi(double v, ComplexDoubleMatrix result) {
+ return subi(new ComplexDouble(v), result);
+ }
+
+ /**
+ * Subtract two matrices, but subtract first from second matrix, that is,
+ * compute <em>result = other - this</em>.
+ * */
+ public ComplexDoubleMatrix rsubi(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ return other.subi(this, result);
+ }
+
+ /** Subtract a matrix from a scalar */
+ public ComplexDoubleMatrix rsubi(ComplexDouble a, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, a.sub(get(i)));
+ return result;
+ }
+
+ public ComplexDoubleMatrix rsubi(double a, ComplexDoubleMatrix result) {
+ return rsubi(new ComplexDouble(a), result);
+ }
+
+ /** (Elementwise) Multiplication */
+ public ComplexDoubleMatrix muli(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return muli(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble c = new ComplexDouble(0.0);
+ ComplexDouble d = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).muli(other.get(i, d)));
+ return result;
+ }
+
+ /** (Elementwise) Multiplication with a scalar */
+ public ComplexDoubleMatrix muli(ComplexDouble v, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ ComplexDouble c = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).muli(v));
+ return result;
+ }
+
+ public ComplexDoubleMatrix muli(double v, ComplexDoubleMatrix result) {
+ return muli(new ComplexDouble(v), result);
+ }
+
+ /** Matrix-Matrix Multiplication */
+ public ComplexDoubleMatrix mmuli(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return muli(other.scalar(), result);
+
+ /* check sizes and resize if necessary */
+ assertMultipliesWith(other);
+ if (result.rows != rows || result.columns != other.columns) {
+ if (result != this && result != other)
+ result.resize(rows, other.columns);
+ else
+ throw new SizeException("Cannot resize result matrix because it is used in-place.");
+ }
+
+ if (result == this || result == other) {
+ /* actually, blas cannot do multiplications in-place. Therefore, we will fake by
+ * allocating a temporary object on the side and copy the result later.
+ */
+ ComplexDoubleMatrix temp = new ComplexDoubleMatrix(result.rows, result.columns);
+ SimpleBlas.gemm(ComplexDouble.UNIT, this, other, ComplexDouble.ZERO, temp);
+ SimpleBlas.copy(temp, result);
+ }
+ else {
+ SimpleBlas.gemm(ComplexDouble.UNIT, this, other, ComplexDouble.ZERO, result);
+ }
+ return result;
+ }
+
+ /** Matrix-Matrix Multiplication with a scalar (for symmetry, does the
+ * same as muli(scalar)
+ */
+ public ComplexDoubleMatrix mmuli(ComplexDouble v, ComplexDoubleMatrix result) {
+ return muli(v, result);
+ }
+
+ public ComplexDoubleMatrix mmuli(double v, ComplexDoubleMatrix result) {
+ return muli(v, result);
+ }
+
+ /** (Elementwise) division */
+ public ComplexDoubleMatrix divi(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return divi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble c1 = new ComplexDouble(0.0);
+ ComplexDouble c2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c1).divi(other.get(i, c2)));
+ return result;
+ }
+
+ /** (Elementwise) division with a scalar */
+ public ComplexDoubleMatrix divi(ComplexDouble a, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ ComplexDouble c = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).divi(a));
+ return result;
+ }
+
+ public ComplexDoubleMatrix divi(double a, ComplexDoubleMatrix result) {
+ return divi(new ComplexDouble(a), result);
+ }
+
+ /**
+ * (Elementwise) division, with operands switched. Computes
+ * <em>result = other / this</em>. */
+ public ComplexDoubleMatrix rdivi(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return divi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble c1 = new ComplexDouble(0.0);
+ ComplexDouble c2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, other.get(i, c1).divi(get(i, c2)));
+ return result;
+ }
+
+ /** (Elementwise) division with a scalar, with operands switched. Computes
+ * <em>result = a / this</em>.*/
+ public ComplexDoubleMatrix rdivi(ComplexDouble a, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ ComplexDouble c1 = new ComplexDouble(0.0);
+ ComplexDouble c2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++) {
+ c1.copy(a);
+ result.put(i, c1.divi(get(i, c2)));
+ }
+ return result;
+ }
+
+ public ComplexDoubleMatrix rdivi(double a, ComplexDoubleMatrix result) {
+ return rdivi(new ComplexDouble(a), result);
+ }
+
+ public ComplexDoubleMatrix negi() {
+ ComplexDouble c = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ put(i, get(i, c).negi());
+ return this;
+ }
+
+ public ComplexDoubleMatrix neg() {
+ return dup().negi();
+ }
+
+ public ComplexDoubleMatrix noti() {
+ ComplexDouble c = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ put(i, get(i, c).isZero() ? 1.0 : 0.0);
+ return this;
+ }
+
+ public ComplexDoubleMatrix not() {
+ return dup().noti();
+ }
+
+ public ComplexDoubleMatrix truthi() {
+ ComplexDouble c = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ put(i, get(i, c).isZero() ? 0.0 : 1.0);
+ return this;
+ }
+
+ public ComplexDoubleMatrix truth() {
+ return dup().truthi();
+ }
+
+ public ComplexDoubleMatrix conji() {
+ ComplexDouble c = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ put(i, get(i, c).conji());
+ return this;
+ }
+
+ /****************************************************************
+ * Rank one-updates
+ */
+
+ /** Computes a rank-1-update A = A + alpha * x * y'. */
+ public ComplexDoubleMatrix rankOneUpdate(ComplexDouble alpha, ComplexDoubleMatrix x, ComplexDoubleMatrix y) {
+ if (rows != x.length)
+ throw new SizeException("Vector x has wrong length (" + x.length + " != " + rows + ").");
+ if (columns != y.length)
+ throw new SizeException("Vector y has wrong length (" + x.length + " != " + columns + ").");
+
+ SimpleBlas.gerc(alpha, x, y, this);
+ return this;
+ }
+
+ public ComplexDoubleMatrix rankOneUpdate(double alpha, ComplexDoubleMatrix x, ComplexDoubleMatrix y) {
+ return rankOneUpdate(new ComplexDouble(alpha), x, y);
+ }
+
+ /** Computes a rank-1-update A = A + alpha * x * x'. */
+ public ComplexDoubleMatrix rankOneUpdate(double alpha, ComplexDoubleMatrix x) {
+ return rankOneUpdate(new ComplexDouble(alpha), x, x);
+ }
+
+ /** Computes a rank-1-update A = A + alpha * x * x'. */
+ public ComplexDoubleMatrix rankOneUpdate(ComplexDouble alpha, ComplexDoubleMatrix x) {
+ return rankOneUpdate(alpha, x, x);
+ }
+
+ /** Computes a rank-1-update A = A + x * x'. */
+ public ComplexDoubleMatrix rankOneUpdate(ComplexDoubleMatrix x) {
+ return rankOneUpdate(1.0, x, x);
+ }
+
+ /** Computes a rank-1-update A = A + x * y'. */
+ public ComplexDoubleMatrix rankOneUpdate(ComplexDoubleMatrix x, ComplexDoubleMatrix y) {
+ return rankOneUpdate(1.0, x, y);
+ }
+
+ /****************************************************************
+ * Logical operations
+ */
+
+ public ComplexDouble sum() {
+ ComplexDouble s = new ComplexDouble(0.0);
+ ComplexDouble c = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ s.addi(get(i, c));
+ return s;
+ }
+
+ public ComplexDouble mean() {
+ return sum().div((double)length);
+ }
+
+ /* computes this^T * other */
+ public ComplexDouble dotc(ComplexDoubleMatrix other) {
+ return SimpleBlas.dotc(this, other);
+ }
+
+ /* computs this^H * other */
+ public ComplexDouble dotu(ComplexDoubleMatrix other) {
+ return SimpleBlas.dotu(this, other);
+ }
+
+ public double norm2() {
+ return SimpleBlas.nrm2(this);
+ }
+
+ public double normmax() {
+ int i = SimpleBlas.iamax(this);
+ return get(i).abs();
+ }
+
+ public double norm1() {
+ return SimpleBlas.asum(this);
+ }
+
+ /** Return a vector containing the sums of the columns (having number of columns many entries) */
+ public ComplexDoubleMatrix columnSums() {
+ ComplexDoubleMatrix v =
+ new ComplexDoubleMatrix(1, columns);
+
+ for (int c = 0; c < columns; c++)
+ v.put(c, getColumn(c).sum());
+
+ return v;
+ }
+
+ public ComplexDoubleMatrix columnMeans() {
+ return columnSums().divi(rows);
+ }
+
+ public ComplexDoubleMatrix rowSums() {
+ ComplexDoubleMatrix v = new ComplexDoubleMatrix(rows);
+
+ for (int r = 0; r < rows; r++)
+ v.put(r, getRow(r).sum());
+
+ return v;
+ }
+
+ public ComplexDoubleMatrix rowMeans() {
+ return rowSums().divi(columns);
+ }
+
+ public ComplexDoubleMatrix getColumn(int c) {
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(rows, 1);
+ Blas.zcopy(rows, data, index(0, c), 1, result.data, 0, 1);
+ return result;
+ }
+
+ public void putColumn(int c, ComplexDoubleMatrix v) {
+ Blas.zcopy(rows, v.data, 0, 1, data, index(0, c), 1);
+ }
+
+ public ComplexDoubleMatrix getRow(int r) {
+ ComplexDoubleMatrix result = new ComplexDoubleMatrix(1, columns);
+ Blas.zcopy(columns, data, index(r, 0), rows, result.data, 0, 1);
+ return result;
+ }
+
+ public void putRow(int r, ComplexDoubleMatrix v) {
+ Blas.zcopy(columns, v.data, 0, 1, data, index(r, 0), rows);
+ }
+
+ /**************************************************************************
+ * Elementwise Functions
+ */
+
+ /** Add a row vector to all rows of the matrix */
+ public void addRowVector(ComplexDoubleMatrix x) {
+ for (int r = 0; r < rows; r++) {
+ Blas.zaxpy(columns, ComplexDouble.UNIT, x.data, 0, 1, data, index(r, 0), rows);
+ }
+ }
+
+ /** Add a vector to all columns of the matrix */
+ public void addColumnVector(ComplexDoubleMatrix x) {
+ for (int c = 0; c < columns; c++) {
+ Blas.zaxpy(rows, ComplexDouble.UNIT, x.data, 0, 1, data, index(0, c), 1);
+ }
+ }
+
+ /** Add a row vector to all rows of the matrix */
+ public void subRowVector(ComplexDoubleMatrix x) {
+ for (int r = 0; r < rows; r++) {
+ Blas.zaxpy(columns, ComplexDouble.NEG_UNIT, x.data, 0, 1, data, index(r, 0), rows);
+ }
+ }
+
+ /** Add a vector to all columns of the matrix */
+ public void subColumnVector(ComplexDoubleMatrix x) {
+ for (int c = 0; c < columns; c++) {
+ Blas.zaxpy(rows, ComplexDouble.NEG_UNIT, x.data, 0, 1, data, index(0, c), 1);
+ }
+ }
+
+ /**
+ * Writes out this matrix to the given data stream.
+ * @param dos the data output stream to write to.
+ * @throws IOException
+ */
+ public void out(DataOutputStream dos) throws IOException {
+ dos.writeUTF("double");
+ dos.writeInt(columns);
+ dos.writeInt(rows);
+
+ dos.writeInt(data.length);
+ for(int i=0; i < data.length;i++)
+ dos.writeDouble(data[i]);
+ }
+
+ /**
+ * Reads in a matrix from the given data stream. Note
+ * that the old data of this matrix will be discarded.
+ * @param dis the data input stream to read from.
+ * @throws IOException
+ */
+ public void in(DataInputStream dis) throws IOException {
+ if(!dis.readUTF().equals("double"))
+ throw new IllegalStateException("The matrix in the specified file is not of the correct type!");
+
+ this.columns = dis.readInt();
+ this.rows = dis.readInt();
+
+ final int MAX = dis.readInt();
+ data = new double[MAX];
+ for(int i=0; i < MAX;i++)
+ data[i] = dis.readDouble();
+ }
+
+ /**
+ * Saves this matrix to the specified file.
+ * @param filename the file to write the matrix in.
+ * @throws IOException thrown on errors while writing the matrix to the file
+ */
+ public void save(String filename) throws IOException {
+ DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename, false));
+ this.out(dos);
+ }
+
+ /**
+ * Loads a matrix from a file into this matrix. Note that the old data
+ * of this matrix will be discarded.
+ * @param filename the file to read the matrix from
+ * @throws IOException thrown on errors while reading the matrix
+ */
+ public void load(String filename) throws IOException {
+ DataInputStream dis = new DataInputStream(new FileInputStream(filename));
+ this.in(dis);
+ }
+
+ /****************************************************************
+ * Autogenerated code
+ */
+
+ /***** Code for operators ***************************************/
+
+ /* Overloads for the usual arithmetic operations */
+ /*#
+ def gen_overloads(base, result_rows, result_cols); <<-EOS
+ public ComplexDoubleMatrix #{base}i(ComplexDoubleMatrix other) {
+ return #{base}i(other, this);
+ }
+
+ public ComplexDoubleMatrix #{base}(ComplexDoubleMatrix other) {
+ return #{base}i(other, new ComplexDoubleMatrix(#{result_rows}, #{result_cols}));
+ }
+
+ public ComplexDoubleMatrix #{base}i(ComplexDouble v) {
+ return #{base}i(v, this);
+ }
+
+ public ComplexDoubleMatrix #{base}i(double v) {
+ return #{base}i(new ComplexDouble(v), this);
+ }
+
+ public ComplexDoubleMatrix #{base}(ComplexDouble v) {
+ return #{base}i(v, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix #{base}(double v) {
+ return #{base}i(new ComplexDouble(v), new ComplexDoubleMatrix(rows, columns));
+ }
+
+ EOS
+ end
+ #*/
+
+ /* Generating code for logical operators. This not only generates the stubs
+ * but really all of the code.
+ */
+
+ /*#
+ def gen_compare(name, op); <<-EOS
+ public ComplexDoubleMatrix #{name}i(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return #{name}i(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble c1 = new ComplexDouble(0.0);
+ ComplexDouble c2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c1).#{op}(other.get(i, c2)) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix #{name}i(ComplexDoubleMatrix other) {
+ return #{name}i(other, this);
+ }
+
+ public ComplexDoubleMatrix #{name}(ComplexDoubleMatrix other) {
+ return #{name}i(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix #{name}i(ComplexDouble value, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+ ComplexDouble c = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).#{op}(value) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix #{name}i(double value, ComplexDoubleMatrix result) {
+ return #{name}i(new ComplexDouble(value), result);
+ }
+
+ public ComplexDoubleMatrix #{name}i(ComplexDouble value) {
+ return #{name}i(value, this);
+ }
+
+ public ComplexDoubleMatrix #{name}i(double value) {
+ return #{name}i(new ComplexDouble(value));
+ }
+
+ public ComplexDoubleMatrix #{name}(ComplexDouble value) {
+ return #{name}i(value, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix #{name}(double value) {
+ return #{name}i(new ComplexDouble(value));
+ }
+
+ EOS
+ end
+ #*/
+
+ /*#
+ def gen_logical(name, op); <<-EOS
+ public ComplexDoubleMatrix #{name}i(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble t1 = new ComplexDouble(0.0);
+ ComplexDouble t2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (!get(i, t1).isZero()) #{op} (!other.get(i, t2).isZero()) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix #{name}i(ComplexDoubleMatrix other) {
+ return #{name}i(other, this);
+ }
+
+ public ComplexDoubleMatrix #{name}(ComplexDoubleMatrix other) {
+ return #{name}i(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix #{name}i(ComplexDouble value, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = !value.isZero();
+ ComplexDouble t = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, !get(i, t).isZero() #{op} val ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix #{name}i(double value, ComplexDoubleMatrix result) {
+ return #{name}i(new ComplexDouble(value), result);
+ }
+
+ public ComplexDoubleMatrix #{name}i(ComplexDouble value) {
+ return #{name}i(value, this);
+ }
+
+ public ComplexDoubleMatrix #{name}i(double value) {
+ return #{name}i(new ComplexDouble(value), this);
+ }
+
+ public ComplexDoubleMatrix #{name}(ComplexDouble value) {
+ return #{name}i(value, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix #{name}(double value) {
+ return #{name}i(new ComplexDouble(value));
+ }
+ EOS
+ end
+ #*/
+
+ /*# collect(gen_overloads('add', 'rows', 'columns'),
+ gen_overloads('sub', 'rows', 'columns'),
+ gen_overloads('rsub', 'rows', 'columns'),
+ gen_overloads('div', 'rows', 'columns'),
+ gen_overloads('rdiv', 'rows', 'columns'),
+ gen_overloads('mul', 'rows', 'columns'),
+ gen_overloads('mmul', 'rows', 'other.columns'),
+ gen_compare('eq', 'eq'),
+ gen_compare('ne', 'eq'),
+ gen_logical('and', '&'),
+ gen_logical('or', '|'),
+ gen_logical('xor', '^'))
+ #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public ComplexDoubleMatrix addi(ComplexDoubleMatrix other) {
+ return addi(other, this);
+ }
+
+ public ComplexDoubleMatrix add(ComplexDoubleMatrix other) {
+ return addi(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix addi(ComplexDouble v) {
+ return addi(v, this);
+ }
+
+ public ComplexDoubleMatrix addi(double v) {
+ return addi(new ComplexDouble(v), this);
+ }
+
+ public ComplexDoubleMatrix add(ComplexDouble v) {
+ return addi(v, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix add(double v) {
+ return addi(new ComplexDouble(v), new ComplexDoubleMatrix(rows, columns));
+ }
+
+
+ public ComplexDoubleMatrix subi(ComplexDoubleMatrix other) {
+ return subi(other, this);
+ }
+
+ public ComplexDoubleMatrix sub(ComplexDoubleMatrix other) {
+ return subi(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix subi(ComplexDouble v) {
+ return subi(v, this);
+ }
+
+ public ComplexDoubleMatrix subi(double v) {
+ return subi(new ComplexDouble(v), this);
+ }
+
+ public ComplexDoubleMatrix sub(ComplexDouble v) {
+ return subi(v, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix sub(double v) {
+ return subi(new ComplexDouble(v), new ComplexDoubleMatrix(rows, columns));
+ }
+
+
+ public ComplexDoubleMatrix rsubi(ComplexDoubleMatrix other) {
+ return rsubi(other, this);
+ }
+
+ public ComplexDoubleMatrix rsub(ComplexDoubleMatrix other) {
+ return rsubi(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix rsubi(ComplexDouble v) {
+ return rsubi(v, this);
+ }
+
+ public ComplexDoubleMatrix rsubi(double v) {
+ return rsubi(new ComplexDouble(v), this);
+ }
+
+ public ComplexDoubleMatrix rsub(ComplexDouble v) {
+ return rsubi(v, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix rsub(double v) {
+ return rsubi(new ComplexDouble(v), new ComplexDoubleMatrix(rows, columns));
+ }
+
+
+ public ComplexDoubleMatrix divi(ComplexDoubleMatrix other) {
+ return divi(other, this);
+ }
+
+ public ComplexDoubleMatrix div(ComplexDoubleMatrix other) {
+ return divi(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix divi(ComplexDouble v) {
+ return divi(v, this);
+ }
+
+ public ComplexDoubleMatrix divi(double v) {
+ return divi(new ComplexDouble(v), this);
+ }
+
+ public ComplexDoubleMatrix div(ComplexDouble v) {
+ return divi(v, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix div(double v) {
+ return divi(new ComplexDouble(v), new ComplexDoubleMatrix(rows, columns));
+ }
+
+
+ public ComplexDoubleMatrix rdivi(ComplexDoubleMatrix other) {
+ return rdivi(other, this);
+ }
+
+ public ComplexDoubleMatrix rdiv(ComplexDoubleMatrix other) {
+ return rdivi(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix rdivi(ComplexDouble v) {
+ return rdivi(v, this);
+ }
+
+ public ComplexDoubleMatrix rdivi(double v) {
+ return rdivi(new ComplexDouble(v), this);
+ }
+
+ public ComplexDoubleMatrix rdiv(ComplexDouble v) {
+ return rdivi(v, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix rdiv(double v) {
+ return rdivi(new ComplexDouble(v), new ComplexDoubleMatrix(rows, columns));
+ }
+
+
+ public ComplexDoubleMatrix muli(ComplexDoubleMatrix other) {
+ return muli(other, this);
+ }
+
+ public ComplexDoubleMatrix mul(ComplexDoubleMatrix other) {
+ return muli(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix muli(ComplexDouble v) {
+ return muli(v, this);
+ }
+
+ public ComplexDoubleMatrix muli(double v) {
+ return muli(new ComplexDouble(v), this);
+ }
+
+ public ComplexDoubleMatrix mul(ComplexDouble v) {
+ return muli(v, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix mul(double v) {
+ return muli(new ComplexDouble(v), new ComplexDoubleMatrix(rows, columns));
+ }
+
+
+ public ComplexDoubleMatrix mmuli(ComplexDoubleMatrix other) {
+ return mmuli(other, this);
+ }
+
+ public ComplexDoubleMatrix mmul(ComplexDoubleMatrix other) {
+ return mmuli(other, new ComplexDoubleMatrix(rows, other.columns));
+ }
+
+ public ComplexDoubleMatrix mmuli(ComplexDouble v) {
+ return mmuli(v, this);
+ }
+
+ public ComplexDoubleMatrix mmuli(double v) {
+ return mmuli(new ComplexDouble(v), this);
+ }
+
+ public ComplexDoubleMatrix mmul(ComplexDouble v) {
+ return mmuli(v, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix mmul(double v) {
+ return mmuli(new ComplexDouble(v), new ComplexDoubleMatrix(rows, columns));
+ }
+
+
+ public ComplexDoubleMatrix eqi(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return eqi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble c1 = new ComplexDouble(0.0);
+ ComplexDouble c2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c1).eq(other.get(i, c2)) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix eqi(ComplexDoubleMatrix other) {
+ return eqi(other, this);
+ }
+
+ public ComplexDoubleMatrix eq(ComplexDoubleMatrix other) {
+ return eqi(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix eqi(ComplexDouble value, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+ ComplexDouble c = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).eq(value) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix eqi(double value, ComplexDoubleMatrix result) {
+ return eqi(new ComplexDouble(value), result);
+ }
+
+ public ComplexDoubleMatrix eqi(ComplexDouble value) {
+ return eqi(value, this);
+ }
+
+ public ComplexDoubleMatrix eqi(double value) {
+ return eqi(new ComplexDouble(value));
+ }
+
+ public ComplexDoubleMatrix eq(ComplexDouble value) {
+ return eqi(value, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix eq(double value) {
+ return eqi(new ComplexDouble(value));
+ }
+
+
+ public ComplexDoubleMatrix nei(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ if (other.isScalar())
+ return nei(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble c1 = new ComplexDouble(0.0);
+ ComplexDouble c2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c1).eq(other.get(i, c2)) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix nei(ComplexDoubleMatrix other) {
+ return nei(other, this);
+ }
+
+ public ComplexDoubleMatrix ne(ComplexDoubleMatrix other) {
+ return nei(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix nei(ComplexDouble value, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+ ComplexDouble c = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).eq(value) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix nei(double value, ComplexDoubleMatrix result) {
+ return nei(new ComplexDouble(value), result);
+ }
+
+ public ComplexDoubleMatrix nei(ComplexDouble value) {
+ return nei(value, this);
+ }
+
+ public ComplexDoubleMatrix nei(double value) {
+ return nei(new ComplexDouble(value));
+ }
+
+ public ComplexDoubleMatrix ne(ComplexDouble value) {
+ return nei(value, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix ne(double value) {
+ return nei(new ComplexDouble(value));
+ }
+
+
+ public ComplexDoubleMatrix andi(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble t1 = new ComplexDouble(0.0);
+ ComplexDouble t2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (!get(i, t1).isZero()) & (!other.get(i, t2).isZero()) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix andi(ComplexDoubleMatrix other) {
+ return andi(other, this);
+ }
+
+ public ComplexDoubleMatrix and(ComplexDoubleMatrix other) {
+ return andi(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix andi(ComplexDouble value, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = !value.isZero();
+ ComplexDouble t = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, !get(i, t).isZero() & val ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix andi(double value, ComplexDoubleMatrix result) {
+ return andi(new ComplexDouble(value), result);
+ }
+
+ public ComplexDoubleMatrix andi(ComplexDouble value) {
+ return andi(value, this);
+ }
+
+ public ComplexDoubleMatrix andi(double value) {
+ return andi(new ComplexDouble(value), this);
+ }
+
+ public ComplexDoubleMatrix and(ComplexDouble value) {
+ return andi(value, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix and(double value) {
+ return andi(new ComplexDouble(value));
+ }
+
+ public ComplexDoubleMatrix ori(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble t1 = new ComplexDouble(0.0);
+ ComplexDouble t2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (!get(i, t1).isZero()) | (!other.get(i, t2).isZero()) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix ori(ComplexDoubleMatrix other) {
+ return ori(other, this);
+ }
+
+ public ComplexDoubleMatrix or(ComplexDoubleMatrix other) {
+ return ori(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix ori(ComplexDouble value, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = !value.isZero();
+ ComplexDouble t = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, !get(i, t).isZero() | val ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix ori(double value, ComplexDoubleMatrix result) {
+ return ori(new ComplexDouble(value), result);
+ }
+
+ public ComplexDoubleMatrix ori(ComplexDouble value) {
+ return ori(value, this);
+ }
+
+ public ComplexDoubleMatrix ori(double value) {
+ return ori(new ComplexDouble(value), this);
+ }
+
+ public ComplexDoubleMatrix or(ComplexDouble value) {
+ return ori(value, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix or(double value) {
+ return ori(new ComplexDouble(value));
+ }
+
+ public ComplexDoubleMatrix xori(ComplexDoubleMatrix other, ComplexDoubleMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexDouble t1 = new ComplexDouble(0.0);
+ ComplexDouble t2 = new ComplexDouble(0.0);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (!get(i, t1).isZero()) ^ (!other.get(i, t2).isZero()) ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix xori(ComplexDoubleMatrix other) {
+ return xori(other, this);
+ }
+
+ public ComplexDoubleMatrix xor(ComplexDoubleMatrix other) {
+ return xori(other, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix xori(ComplexDouble value, ComplexDoubleMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = !value.isZero();
+ ComplexDouble t = new ComplexDouble(0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, !get(i, t).isZero() ^ val ? 1.0 : 0.0);
+ return result;
+ }
+
+ public ComplexDoubleMatrix xori(double value, ComplexDoubleMatrix result) {
+ return xori(new ComplexDouble(value), result);
+ }
+
+ public ComplexDoubleMatrix xori(ComplexDouble value) {
+ return xori(value, this);
+ }
+
+ public ComplexDoubleMatrix xori(double value) {
+ return xori(new ComplexDouble(value), this);
+ }
+
+ public ComplexDoubleMatrix xor(ComplexDouble value) {
+ return xori(value, new ComplexDoubleMatrix(rows, columns));
+ }
+
+ public ComplexDoubleMatrix xor(double value) {
+ return xori(new ComplexDouble(value));
+ }
+//RJPP-END--------------------------------------------------------------
+}
diff --git a/src/org/jblas/la/ComplexFloatMatrix.java b/src/org/jblas/la/ComplexFloatMatrix.java
new file mode 100644
index 0000000..1750df0
--- /dev/null
+++ b/src/org/jblas/la/ComplexFloatMatrix.java
@@ -0,0 +1,2011 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.exceptions.SizeException;
+import org.jblas.core.ComplexFloat;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class ComplexFloatMatrix {
+
+ public int rows;
+ public int columns;
+ public int length;
+ public float[] data = null; // rows are contiguous
+
+ /**************************************************************************
+ *
+ * Constructors and factory functions
+ *
+ **************************************************************************/
+
+ /** Create a new matrix with <i>newRows</i> rows, <i>newColumns</i> columns
+ * using <i>newData></i> as the data. The length of the data is not checked!
+ */
+ public ComplexFloatMatrix(int newRows, int newColumns, float... newData) {
+ rows = newRows;
+ columns = newColumns;
+ length = rows * columns;
+
+ if (newData.length != 2 * newRows * newColumns)
+ throw new IllegalArgumentException(
+ "Passed data must match matrix dimensions.");
+
+ data = newData;
+ }
+
+ /**
+ * Creates a new <i>n</i> times <i>m</i> <tt>ComplexFloatMatrix</tt>.
+ * @param newRows the number of rows (<i>n</i>) of the new matrix.
+ * @param newColumns the number of columns (<i>m</i>) of the new matrix.
+ */
+ public ComplexFloatMatrix(int newRows, int newColumns) {
+ this(newRows, newColumns, new float[2 * newRows * newColumns]);
+ }
+
+ /**
+ * Creates a new <tt>ComplexFloatMatrix</tt> of size 0 times 0.
+ */
+ public ComplexFloatMatrix() {
+ this(0, 0, null);
+ }
+
+ /**
+ * Create a Matrix of length <tt>len</tt>. By default, this creates a row vector.
+ * @param len
+ */
+ public ComplexFloatMatrix(int len) {
+ this(len, 1, new float[2 * len]);
+ }
+
+ public ComplexFloatMatrix(float[] newData) {
+ this(newData.length/2);
+
+ data = newData;
+ }
+
+ public ComplexFloatMatrix(ComplexFloat[] newData) {
+ this(newData.length);
+
+ for (int i = 0; i < newData.length; i++)
+ put(i, newData[i]);
+ }
+
+
+ /** Construct a complex matrix from a real matrix. */
+ public ComplexFloatMatrix(FloatMatrix m) {
+ this(m.rows, m.columns);
+
+ Blas.scopy(m.length, m.data, 0, 1, data, 0, 2);
+ }
+
+ /** Construct a complex matrix from separate real and imaginary parts. Either
+ * part can be set to null in which case it will be ignored.
+ */
+ public ComplexFloatMatrix(FloatMatrix real, FloatMatrix imag) {
+ this(real.rows, real.columns);
+ real.assertSameSize(imag);
+
+ if (real != null)
+ Blas.scopy(length, real.data, 0, 1, data, 0, 2);
+ if (imag != null)
+ Blas.scopy(length, imag.data, 0, 1, data, 1, 2);
+ }
+
+ /**
+ * Creates a new matrix by reading it from a file.
+ * @param filename the path and name of the file to read the matrix from
+ * @throws IOException
+ */
+ public ComplexFloatMatrix(String filename) throws IOException {
+ load(filename);
+ }
+
+ /**
+ * Creates a new <i>n</i> times <i>m</i> <tt>ComplexFloatMatrix</tt> from
+ * the given <i>n</i> times <i>m</i> 2D data array. The first dimension of the array makes the
+ * rows (<i>n</i>) and the second dimension the columns (<i>m</i>). For example, the
+ * given code <br/><br/>
+ * <code>new ComplexFloatMatrix(new float[][]{{1d, 2d, 3d}, {4d, 5d, 6d}, {7d, 8d, 9d}}).print();</code><br/><br/>
+ * will constructs the following matrix:
+ * <pre>
+ * 1.0f 2.0f 3.0f
+ * 4.0f 5.0f 6.0f
+ * 7.0f 8.0f 9.0f
+ * </pre>.
+ * @param data <i>n</i> times <i>m</i> data array
+ */
+ public ComplexFloatMatrix(float[][] data) {
+ this(data.length, data[0].length);
+
+ for (int r = 0; r < rows; r++)
+ assert(data[r].length == columns);
+
+ for (int r = 0; r < rows; r++)
+ for (int c = 0; c < columns; c++)
+ put(r, c, data[r][c]);
+ }
+
+ /**
+ * Creates a new matrix in which all values are equal 0.
+ * @param rows number of rows
+ * @param columns number of columns
+ * @return new matrix
+ */
+ public static ComplexFloatMatrix zeros(int rows, int columns) {
+ return new ComplexFloatMatrix(rows, columns);
+ }
+
+ public static ComplexFloatMatrix zeros(int length) {
+ return zeros(length, 1);
+ }
+
+ /**
+ * Creates a new matrix in which all values are equal 1.
+ * @param rows number of rows
+ * @param columns number of columns
+ * @return new matrix
+ */
+ public static ComplexFloatMatrix ones(int rows, int columns) {
+ ComplexFloatMatrix m = new ComplexFloatMatrix(rows, columns);
+
+ for (int i = 0; i < rows * columns; i++)
+ m.put(i, 1.0f);
+
+ return m;
+ }
+
+ public static ComplexFloatMatrix ones(int length) {
+ return ones(length, 1);
+ }
+
+ /**
+ * Creates a new matrix where the values of the given vector are the diagonal values of
+ * the matrix.
+ * @param x the diagonal values
+ * @return new matrix
+ */
+ public static ComplexFloatMatrix diag(ComplexFloatMatrix x) {
+ ComplexFloatMatrix m = new ComplexFloatMatrix(x.length, x.length);
+
+ for (int i = 0; i < x.length; i++)
+ m.put(i, i, x.get(i));
+
+ return m;
+ }
+
+ /**
+ * Create a 1 * 1 - matrix. For many operations, this matrix functions like a
+ * normal float
+ * @param s value of the matrix
+ * @return the constructed ComplexFloatMatrix
+ */
+ public static ComplexFloatMatrix scalar(float s) {
+ ComplexFloatMatrix m = new ComplexFloatMatrix(1, 1);
+ m.put(0, 0, s);
+ return m;
+ }
+
+ /** Test whether a matrix is scalar */
+ public boolean isScalar() {
+ return length == 1;
+ }
+
+ /** Return the first element of the matrix */
+ public ComplexFloat scalar() {
+ return get(0);
+ }
+
+ public static ComplexFloatMatrix concatHorizontally(ComplexFloatMatrix A, ComplexFloatMatrix B) {
+ if (A.rows != B.rows)
+ throw new SizeException("Matrices don't have same number of rows.");
+
+ ComplexFloatMatrix result = new ComplexFloatMatrix(A.rows, A.columns + B.columns);
+ SimpleBlas.copy(A, result);
+ Blas.ccopy(B.length, B.data, 0, 1, result.data, A.length, 1);
+ return result;
+ }
+
+ public static ComplexFloatMatrix concatVertically(ComplexFloatMatrix A, ComplexFloatMatrix B) {
+ if (A.columns != B.columns)
+ throw new SizeException("Matrices don't have same number of columns.");
+
+ ComplexFloatMatrix result = new ComplexFloatMatrix(A.rows + B.rows, A.columns);
+
+ for (int i = 0; i < A.columns; i++) {
+ Blas.ccopy(A.rows, A.data, A.index(0, i), 1, result.data, result.index(0, i), 1);
+ Blas.ccopy(B.rows, B.data, B.index(0, i), 1, result.data, result.index(A.rows, i), 1);
+ }
+
+ return result;
+ }
+
+ /**************************************************************************
+ * Working with slices (Man! 30+ methods just to make this a bit flexible...)
+ */
+
+ public ComplexFloatMatrix get(int[] indices) {
+ ComplexFloatMatrix result = new ComplexFloatMatrix(indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ result.put(i, get(indices[i]));
+
+ return result;
+ }
+
+ public ComplexFloatMatrix get(int r, int[] indices) {
+ ComplexFloatMatrix result = new ComplexFloatMatrix(1, indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ result.put(i, get(r, indices[i]));
+
+ return result;
+ }
+
+ public ComplexFloatMatrix get(int[] indices, int c) {
+ ComplexFloatMatrix result = new ComplexFloatMatrix(indices.length, c);
+
+ for (int i = 0; i < indices.length; i++)
+ result.put(i, get(indices[i], c));
+
+ return result;
+ }
+
+ public ComplexFloatMatrix get(int[] rindices, int[] cindices) {
+ ComplexFloatMatrix result = new ComplexFloatMatrix(rindices.length, cindices.length);
+
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ result.put(i, j, get(rindices[i], cindices[j]));
+
+ return result;
+ }
+
+ public ComplexFloatMatrix get(ComplexFloatMatrix indices) {
+ return get(indices.findIndices());
+ }
+
+ public ComplexFloatMatrix get(int r, ComplexFloatMatrix indices) {
+ return get(r, indices.findIndices());
+ }
+
+ public ComplexFloatMatrix get(ComplexFloatMatrix indices, int c) {
+ return get(indices.findIndices(), c);
+ }
+
+ public ComplexFloatMatrix get(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices) {
+ return get(rindices.findIndices(), cindices.findIndices());
+ }
+
+ private void checkLength(int l) {
+ if (length != l)
+ throw new SizeException("Matrix does not have the necessary length (" + length + " != " + l + ").");
+ }
+
+ private void checkRows(int r) {
+ if (rows != r)
+ throw new SizeException("Matrix does not have the necessary length (" + length + " != " + r + ").");
+ }
+
+ private void checkColumns(int c) {
+ if (columns != c)
+ throw new SizeException("Matrix does not have the necessary length (" + length + " != " + c + ").");
+ }
+
+ public ComplexFloatMatrix put(int[] indices, ComplexFloatMatrix x) {
+ if (x.isScalar())
+ return put(indices, x.scalar());
+ x.checkLength(indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], x.get(i));
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int r, int[] indices, ComplexFloatMatrix x) {
+ if (x.isScalar())
+ return put(r, indices, x.scalar());
+ x.checkColumns(indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ put(r, indices[i], x.get(i));
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int[] indices, int c, ComplexFloatMatrix x) {
+ if (x.isScalar())
+ return put(indices, c, x.scalar());
+ x.checkRows(indices.length);
+
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], c, x.get(i));
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int[] rindices, int[] cindices, ComplexFloatMatrix x) {
+ if (x.isScalar())
+ return put(rindices, cindices, x.scalar());
+ x.checkRows(rindices.length);
+ x.checkColumns(cindices.length);
+
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ put(rindices[i], cindices[j], x.get(i,j));
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int[] indices, float v) {
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix putReal(int[] indices, float v) {
+ return put(indices, v);
+ }
+
+ public ComplexFloatMatrix putImag(int[] indices, float v) {
+ for (int i = 0; i < indices.length; i++)
+ putImag(indices[i], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int[] indices, ComplexFloat v) {
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int r, int[] indices, float v) {
+ for (int i = 0; i < indices.length; i++)
+ put(r, indices[i], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix putReal(int r, int[] indices, float v) {
+ return put(r, indices, v);
+ }
+
+ public ComplexFloatMatrix putImag(int r, int[] indices, float v) {
+ for (int i = 0; i < indices.length; i++)
+ putImag(r, indices[i], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int r, int[] indices, ComplexFloat v) {
+ for (int i = 0; i < indices.length; i++)
+ put(r, indices[i], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int[] indices, int c, float v) {
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], c, v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix putReal(int[] indices, int c, float v) {
+ return put(indices, c, v);
+ }
+
+ public ComplexFloatMatrix putImag(int[] indices, int c, float v) {
+ for (int i = 0; i < indices.length; i++)
+ putImag(indices[i], c, v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int[] indices, int c, ComplexFloat v) {
+ for (int i = 0; i < indices.length; i++)
+ put(indices[i], c, v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int[] rindices, int[] cindices, float v) {
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ put(rindices[i], cindices[j], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix putReal(int[] rindices, int[] cindices, float v) {
+ return put(rindices, cindices, v);
+ }
+
+ public ComplexFloatMatrix putImag(int[] rindices, int[] cindices, float v) {
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ put(rindices[i], cindices[j], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int[] rindices, int[] cindices, ComplexFloat v) {
+ for (int i = 0; i < rindices.length; i++)
+ for (int j = 0; j < cindices.length; j++)
+ put(rindices[i], cindices[j], v);
+
+ return this;
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix indices, ComplexFloatMatrix v) {
+ return put(indices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix put(int r, ComplexFloatMatrix indices, ComplexFloatMatrix v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix indices, int c, ComplexFloatMatrix v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, ComplexFloatMatrix v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix indices, float v) {
+ return put(indices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix putReal(ComplexFloatMatrix indices, float v) {
+ return put(indices, v);
+ }
+
+ public ComplexFloatMatrix putImag(ComplexFloatMatrix indices, float v) {
+ return putImag(indices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix indices, ComplexFloat v) {
+ return put(indices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix put(int r, ComplexFloatMatrix indices, float v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix putReal(int r, ComplexFloatMatrix indices, float v) {
+ return put(r, indices, v);
+ }
+
+ public ComplexFloatMatrix putImag(int r, ComplexFloatMatrix indices, float v) {
+ return putImag(r, indices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix put(int r, ComplexFloatMatrix indices, ComplexFloat v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix indices, int c, float v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ public ComplexFloatMatrix putReal(ComplexFloatMatrix indices, int c, float v) {
+ return put(indices, c, v);
+ }
+
+ public ComplexFloatMatrix putImag(ComplexFloatMatrix indices, int c, float v) {
+ return putImag(indices.findIndices(), c, v);
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix indices, int c, ComplexFloat v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, float v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix putReal(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, float v) {
+ return putReal(rindices, cindices, v);
+ }
+
+ public ComplexFloatMatrix putImag(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, float v) {
+ return putImag(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ public ComplexFloatMatrix put(ComplexFloatMatrix rindices, ComplexFloatMatrix cindices, ComplexFloat v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+
+ public int[] findIndices() {
+ int len = 0;
+ for (int i = 0; i < length; i++)
+ if (!get(i).isZero())
+ len++;
+
+ int[] indices = new int[len];
+ int c = 0;
+
+ for (int i = 0; i < length; i++)
+ if (!get(i).isZero())
+ indices[c++] = i;
+
+ return indices;
+ }
+
+ /**************************************************************************
+ * Basic operations (copying, resizing, element access)
+ */
+
+ /** Return transposed copy of this matrix */
+ public ComplexFloatMatrix transpose() {
+ ComplexFloatMatrix result = new ComplexFloatMatrix(columns, rows);
+
+ for (int i = 0; i < rows; i++)
+ for (int j = 0; j < columns; j++)
+ result.put(j, i, get(i, j));
+
+ return result;
+ }
+
+
+ /** Compare two matrices.
+ * @param o Object to compare to
+ * @return true if and only if other is also a ComplexFloatMatrix which has the same size and the
+ * maximal absolute difference in matrix elements is smaller thatn 1e-6. */
+ public boolean equals(Object o) {
+ if (!(o instanceof ComplexFloatMatrix))
+ return false;
+
+ ComplexFloatMatrix other = (ComplexFloatMatrix) o;
+
+ if (!sameSize(other))
+ return false;
+
+ FloatMatrix diff = MatrixFunctions.absi(sub(other)).getReal();
+
+ return diff.max() / (rows * columns) < 1e-6;
+ }
+
+
+ /** Resize the matrix. All elements will be set to zero. */
+ public void resize(int newRows, int newColumns) {
+ rows = newRows;
+ columns = newColumns;
+ length = newRows * newColumns;
+ data = new float[2 * rows * columns];
+ }
+
+
+ /** Reshape the matrix. Number of elements must not change. */
+ public ComplexFloatMatrix reshape(int newRows, int newColumns) {
+ if (length != newRows * newColumns)
+ throw new IllegalArgumentException(
+ "Number of elements must not change.");
+
+ rows = newRows;
+ columns = newColumns;
+
+ return this;
+ }
+
+ /** Checks whether two matrices have the same size. */
+ public boolean sameSize(ComplexFloatMatrix a) {
+ return rows == a.rows && columns == a.columns;
+ }
+
+ /**
+ * Assert that two matrices have the same size.
+ *
+ * @param a the other matrix
+ * @throws SizeException if matrix sizes don't match.
+ * */
+ public void assertSameSize(ComplexFloatMatrix a) {
+ if (!sameSize(a))
+ throw new SizeException("Matrices must have the same size.");
+ }
+
+ /**
+ * Check whether this can be multiplied with a.
+ *
+ * @param a right-hand-side of the multiplication.
+ * @return true iff <tt>this.columns == a.rows</tt>
+ */
+ public boolean multipliesWith(ComplexFloatMatrix a) {
+ return columns == a.rows;
+ }
+
+ public void assertMultipliesWith(ComplexFloatMatrix a) {
+ if (!multipliesWith(a))
+ throw new SizeException("Number of columns of left matrix must be equal to number of rows of right matrix.");
+ }
+
+ public boolean sameLength(ComplexFloatMatrix a) {
+ return length == a.length;
+ }
+
+ public void assertSameLength(ComplexFloatMatrix a) {
+ if (!sameLength(a))
+ throw new SizeException("Matrices must have same length (is: " + length + " and " + a.length + ")");
+ }
+
+ /** Copy ComplexFloatMatrix a to this. this a is resized if necessary. */
+ public ComplexFloatMatrix copy(ComplexFloatMatrix a) {
+ if (!sameSize(a))
+ resize(a.rows, a.columns);
+
+ SimpleBlas.copy(a, this);
+ return a;
+ }
+
+ /** Returns a duplicate of this matrix. Geometry is the same (including offsets, transpose, etc.),
+ * but the buffer is not shared.
+ */
+ public ComplexFloatMatrix dup() {
+ ComplexFloatMatrix out = new ComplexFloatMatrix(rows, columns);
+
+ System.arraycopy(out.data, 0, data, 0, 2 * length);
+
+ return out;
+ }
+
+ public ComplexFloatMatrix swapColumns(int i, int j) {
+ Blas.cswap(rows, data, index(0, i), 1, data, index(0, j), 1);
+ return this;
+ }
+
+ public ComplexFloatMatrix swapRows(int i, int j) {
+ Blas.cswap(columns, data, index(i, 0), rows, data, index(j, 0), rows);
+ return this;
+ }
+
+ /** Set matrix element */
+ public ComplexFloatMatrix put(int rowIndex, int columnIndex, float value) {
+ data[2*index(rowIndex, columnIndex)] = value;
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int rowIndex, int columnIndex, ComplexFloat value) {
+ int i = 2*index(rowIndex, columnIndex);
+ data[i] = value.real(); data[i+1] = value.imag();
+ return this;
+ }
+
+ public ComplexFloatMatrix putReal(int rowIndex, int columnIndex, float value) {
+ data[2*index(rowIndex, columnIndex)] = value;
+ return this;
+ }
+
+ public ComplexFloatMatrix putImag(int rowIndex, int columnIndex, float value) {
+ data[2*index(rowIndex, columnIndex)+1] = value;
+ return this;
+ }
+
+ /** Retrieve matrix element */
+ public ComplexFloat get(int rowIndex, int columnIndex) {
+ int i = 2*index(rowIndex, columnIndex);
+ return new ComplexFloat(data[i], data[i+1]);
+ }
+
+ public FloatMatrix getReal() {
+ FloatMatrix result = new FloatMatrix(rows, columns);
+
+ Blas.scopy(length, data, 0, 2, result.data, 0, 1);
+
+ return result;
+ }
+
+ /** Get index of an element */
+ public int index(int rowIndex, int columnIndex) {
+ //System.out.printf("Index for (%d, %d) -> %d\n", rowIndex, columnIndex, (rows * columnIndex + rowIndex) * 2);
+ return rows * columnIndex + rowIndex;
+ }
+
+ public ComplexFloat get(int i) {
+ return new ComplexFloat(data[i * 2], data[i * 2 + 1]);
+ }
+
+ public ComplexFloat get(int i, ComplexFloat result) {
+ return result.set(data[i * 2], data[i*2+1]);
+ }
+
+ public float getReal(int i) {
+ return data[2*i];
+ }
+
+ public float getImag(int i) {
+ return data[2*i + 1];
+ }
+
+ public ComplexFloatMatrix put(int i, float v) {
+ data[2*i] = v;
+ return this;
+ }
+
+ public ComplexFloatMatrix put(int i, ComplexFloat v) {
+ data[2*i] = v.real();
+ data[2*i+1] = v.imag();
+ return this;
+ }
+
+ public ComplexFloatMatrix putReal(int i, float v) {
+ return put(i, v);
+ }
+
+ public ComplexFloatMatrix putImag(int i, float v) {
+ data[2*i+1] = v;
+ return this;
+ }
+
+ public int getRows() {
+ return rows;
+ }
+
+ public int getColumns() {
+ return columns;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ /** Checks whether the matrix is empty. */
+ public boolean isEmpty() {
+ return columns == 0 || rows == 0;
+ }
+
+ /** Checks whether the matrix is square. */
+ public boolean isSquare() {
+ return columns == rows;
+ }
+
+ public void assertSquare() {
+ if (!isSquare())
+ throw new SizeException("Matrix must be square!");
+ }
+
+ /** Checks whether the matrix is a vector. */
+ public boolean isVector() {
+ return columns == 1 || rows == 1;
+ }
+
+ public boolean isRowVector() {
+ return columns == 1;
+ }
+
+ public boolean isColumnVector() {
+ return rows == 1;
+ }
+
+ /** Get diagonal of the matrix. */
+ public ComplexFloatMatrix diag() {
+ ComplexFloatMatrix d = new ComplexFloatMatrix(rows);
+ Blas.ccopy(rows, data, 0, rows + 1, d.data, 0, 1);
+ return d;
+ }
+
+ /** Get real part of the matrix. */
+ public FloatMatrix real() {
+ FloatMatrix result = new FloatMatrix(rows, columns);
+ Blas.scopy(length, data, 0, 2, result.data, 0, 1);
+ return result;
+ }
+
+ /** Get imaginary part of the matrix. */
+ public FloatMatrix imag() {
+ FloatMatrix result = new FloatMatrix(rows, columns);
+ Blas.scopy(length, data, 1, 2, result.data, 0, 1);
+ return result;
+ }
+
+
+ /**
+ * Pretty-print this matrix to <tt>System.out</tt>.
+ * */
+ public void print() {
+ System.out.println(toString());
+ }
+
+ /**
+ * Generate string representation of this matrix
+ * (multi-line).
+ * */
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+
+ s.append("[");
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < columns; j++) {
+ s.append(get(i, j));
+ if (j < columns - 1)
+ s.append(", ");
+ }
+ if (i < rows - 1)
+ s.append("; ");
+ }
+
+ s.append("]");
+
+ return s.toString();
+ }
+
+ public float[] toDoubleArray() {
+ float[] array = new float[2*length];
+
+ for (int i = 0; i < 2*length; i++)
+ array[i] = data[i];
+
+ return array;
+ }
+
+ public ComplexFloat[] toArray() {
+ ComplexFloat[] array = new ComplexFloat[length];
+
+ for (int i = 0; i < length; i++)
+ array[i] = get(i);
+
+ return array;
+ }
+
+ public ComplexFloat[][] toArray2() {
+ ComplexFloat[][] array = new ComplexFloat[rows][columns];
+
+ for (int r = 0; r < rows; r++)
+ for (int c = 0; c < columns; c++)
+ array[r][c] = get(r, c);
+
+ return array;
+ }
+
+ public boolean[] toBooleanArray() {
+ boolean[] array = new boolean[length];
+
+ for (int i = 0; i < length; i++)
+ array[i] = get(i).isZero() ? false : true;
+
+ return array;
+ }
+
+ public boolean[][] toBooleanArray2() {
+ boolean[][] array = new boolean[rows][columns];
+
+ for (int r = 0; r < rows; r++)
+ for (int c = 0; c < columns; c++)
+ array[r][c] = get(r, c).isZero() ? false : true;
+
+ return array;
+ }
+
+ /**************************************************************************
+ * Arithmetic Operations
+ */
+
+ /**
+ * Ensures that the result vector has the same length as this. If not,
+ * resizing result is tried, which fails if result == this or result == other.
+ */
+ private void ensureResultLength(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (!sameLength(result)) {
+ if (result == this || result == other)
+ throw new SizeException("Cannot resize result matrix because it is used in-place.");
+ result.resize(rows, columns);
+ }
+ }
+
+ /** Add two matrices. */
+ public ComplexFloatMatrix addi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return addi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ if (result == this)
+ SimpleBlas.axpy(ComplexFloat.UNIT, other, result);
+ else if (result == other)
+ SimpleBlas.axpy(ComplexFloat.UNIT, this, result);
+ else {
+ SimpleBlas.copy(this, result);
+ SimpleBlas.axpy(ComplexFloat.UNIT, other, result);
+ }
+
+ return result;
+ }
+
+ /** Add a scalar to a matrix. */
+ public ComplexFloatMatrix addi(ComplexFloat v, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i).add(v));
+ return result;
+ }
+
+ public ComplexFloatMatrix addi(float v, ComplexFloatMatrix result) {
+ return addi(new ComplexFloat(v), result);
+ }
+
+ /** Subtract two matrices. */
+ public ComplexFloatMatrix subi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return subi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ if (result == this)
+ SimpleBlas.axpy(ComplexFloat.NEG_UNIT, other, result);
+ else if (result == other) {
+ SimpleBlas.scal(ComplexFloat.NEG_UNIT, result);
+ SimpleBlas.axpy(ComplexFloat.UNIT, this, result);
+ }
+ else {
+ SimpleBlas.copy(this, result);
+ SimpleBlas.axpy(ComplexFloat.NEG_UNIT, other, result);
+ }
+ return result;
+ }
+
+ /** Subtract a scalar from a matrix */
+ public ComplexFloatMatrix subi(ComplexFloat v, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i).sub(v));
+ return result;
+ }
+
+ public ComplexFloatMatrix subi(float v, ComplexFloatMatrix result) {
+ return subi(new ComplexFloat(v), result);
+ }
+
+ /**
+ * Subtract two matrices, but subtract first from second matrix, that is,
+ * compute <em>result = other - this</em>.
+ * */
+ public ComplexFloatMatrix rsubi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ return other.subi(this, result);
+ }
+
+ /** Subtract a matrix from a scalar */
+ public ComplexFloatMatrix rsubi(ComplexFloat a, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, a.sub(get(i)));
+ return result;
+ }
+
+ public ComplexFloatMatrix rsubi(float a, ComplexFloatMatrix result) {
+ return rsubi(new ComplexFloat(a), result);
+ }
+
+ /** (Elementwise) Multiplication */
+ public ComplexFloatMatrix muli(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return muli(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat c = new ComplexFloat(0.0f);
+ ComplexFloat d = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).muli(other.get(i, d)));
+ return result;
+ }
+
+ /** (Elementwise) Multiplication with a scalar */
+ public ComplexFloatMatrix muli(ComplexFloat v, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+
+ ComplexFloat c = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).muli(v));
+ return result;
+ }
+
+ public ComplexFloatMatrix muli(float v, ComplexFloatMatrix result) {
+ return muli(new ComplexFloat(v), result);
+ }
+
+ /** Matrix-Matrix Multiplication */
+ public ComplexFloatMatrix mmuli(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return muli(other.scalar(), result);
+
+ /* check sizes and resize if necessary */
+ assertMultipliesWith(other);
+ if (result.rows != rows || result.columns != other.columns) {
+ if (result != this && result != other)
+ result.resize(rows, other.columns);
+ else
+ throw new SizeException("Cannot resize result matrix because it is used in-place.");
+ }
+
+ if (result == this || result == other) {
+ /* actually, blas cannot do multiplications in-place. Therefore, we will fake by
+ * allocating a temporary object on the side and copy the result later.
+ */
+ ComplexFloatMatrix temp = new ComplexFloatMatrix(result.rows, result.columns);
+ SimpleBlas.gemm(ComplexFloat.UNIT, this, other, ComplexFloat.ZERO, temp);
+ SimpleBlas.copy(temp, result);
+ }
+ else {
+ SimpleBlas.gemm(ComplexFloat.UNIT, this, other, ComplexFloat.ZERO, result);
+ }
+ return result;
+ }
+
+ /** Matrix-Matrix Multiplication with a scalar (for symmetry, does the
+ * same as muli(scalar)
+ */
+ public ComplexFloatMatrix mmuli(ComplexFloat v, ComplexFloatMatrix result) {
+ return muli(v, result);
+ }
+
+ public ComplexFloatMatrix mmuli(float v, ComplexFloatMatrix result) {
+ return muli(v, result);
+ }
+
+ /** (Elementwise) division */
+ public ComplexFloatMatrix divi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return divi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat c1 = new ComplexFloat(0.0f);
+ ComplexFloat c2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c1).divi(other.get(i, c2)));
+ return result;
+ }
+
+ /** (Elementwise) division with a scalar */
+ public ComplexFloatMatrix divi(ComplexFloat a, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+
+ ComplexFloat c = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).divi(a));
+ return result;
+ }
+
+ public ComplexFloatMatrix divi(float a, ComplexFloatMatrix result) {
+ return divi(new ComplexFloat(a), result);
+ }
+
+ /**
+ * (Elementwise) division, with operands switched. Computes
+ * <em>result = other / this</em>. */
+ public ComplexFloatMatrix rdivi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return divi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat c1 = new ComplexFloat(0.0f);
+ ComplexFloat c2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, other.get(i, c1).divi(get(i, c2)));
+ return result;
+ }
+
+ /** (Elementwise) division with a scalar, with operands switched. Computes
+ * <em>result = a / this</em>.*/
+ public ComplexFloatMatrix rdivi(ComplexFloat a, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+
+ ComplexFloat c1 = new ComplexFloat(0.0f);
+ ComplexFloat c2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++) {
+ c1.copy(a);
+ result.put(i, c1.divi(get(i, c2)));
+ }
+ return result;
+ }
+
+ public ComplexFloatMatrix rdivi(float a, ComplexFloatMatrix result) {
+ return rdivi(new ComplexFloat(a), result);
+ }
+
+ public ComplexFloatMatrix negi() {
+ ComplexFloat c = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ put(i, get(i, c).negi());
+ return this;
+ }
+
+ public ComplexFloatMatrix neg() {
+ return dup().negi();
+ }
+
+ public ComplexFloatMatrix noti() {
+ ComplexFloat c = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ put(i, get(i, c).isZero() ? 1.0f : 0.0f);
+ return this;
+ }
+
+ public ComplexFloatMatrix not() {
+ return dup().noti();
+ }
+
+ public ComplexFloatMatrix truthi() {
+ ComplexFloat c = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ put(i, get(i, c).isZero() ? 0.0f : 1.0f);
+ return this;
+ }
+
+ public ComplexFloatMatrix truth() {
+ return dup().truthi();
+ }
+
+ public ComplexFloatMatrix conji() {
+ ComplexFloat c = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ put(i, get(i, c).conji());
+ return this;
+ }
+
+ /****************************************************************
+ * Rank one-updates
+ */
+
+ /** Computes a rank-1-update A = A + alpha * x * y'. */
+ public ComplexFloatMatrix rankOneUpdate(ComplexFloat alpha, ComplexFloatMatrix x, ComplexFloatMatrix y) {
+ if (rows != x.length)
+ throw new SizeException("Vector x has wrong length (" + x.length + " != " + rows + ").");
+ if (columns != y.length)
+ throw new SizeException("Vector y has wrong length (" + x.length + " != " + columns + ").");
+
+ SimpleBlas.gerc(alpha, x, y, this);
+ return this;
+ }
+
+ public ComplexFloatMatrix rankOneUpdate(float alpha, ComplexFloatMatrix x, ComplexFloatMatrix y) {
+ return rankOneUpdate(new ComplexFloat(alpha), x, y);
+ }
+
+ /** Computes a rank-1-update A = A + alpha * x * x'. */
+ public ComplexFloatMatrix rankOneUpdate(float alpha, ComplexFloatMatrix x) {
+ return rankOneUpdate(new ComplexFloat(alpha), x, x);
+ }
+
+ /** Computes a rank-1-update A = A + alpha * x * x'. */
+ public ComplexFloatMatrix rankOneUpdate(ComplexFloat alpha, ComplexFloatMatrix x) {
+ return rankOneUpdate(alpha, x, x);
+ }
+
+ /** Computes a rank-1-update A = A + x * x'. */
+ public ComplexFloatMatrix rankOneUpdate(ComplexFloatMatrix x) {
+ return rankOneUpdate(1.0f, x, x);
+ }
+
+ /** Computes a rank-1-update A = A + x * y'. */
+ public ComplexFloatMatrix rankOneUpdate(ComplexFloatMatrix x, ComplexFloatMatrix y) {
+ return rankOneUpdate(1.0f, x, y);
+ }
+
+ /****************************************************************
+ * Logical operations
+ */
+
+ public ComplexFloat sum() {
+ ComplexFloat s = new ComplexFloat(0.0f);
+ ComplexFloat c = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ s.addi(get(i, c));
+ return s;
+ }
+
+ public ComplexFloat mean() {
+ return sum().div((float)length);
+ }
+
+ /* computes this^T * other */
+ public ComplexFloat dotc(ComplexFloatMatrix other) {
+ return SimpleBlas.dotc(this, other);
+ }
+
+ /* computs this^H * other */
+ public ComplexFloat dotu(ComplexFloatMatrix other) {
+ return SimpleBlas.dotu(this, other);
+ }
+
+ public float norm2() {
+ return SimpleBlas.nrm2(this);
+ }
+
+ public float normmax() {
+ int i = SimpleBlas.iamax(this);
+ return get(i).abs();
+ }
+
+ public float norm1() {
+ return SimpleBlas.asum(this);
+ }
+
+ /** Return a vector containing the sums of the columns (having number of columns many entries) */
+ public ComplexFloatMatrix columnSums() {
+ ComplexFloatMatrix v =
+ new ComplexFloatMatrix(1, columns);
+
+ for (int c = 0; c < columns; c++)
+ v.put(c, getColumn(c).sum());
+
+ return v;
+ }
+
+ public ComplexFloatMatrix columnMeans() {
+ return columnSums().divi(rows);
+ }
+
+ public ComplexFloatMatrix rowSums() {
+ ComplexFloatMatrix v = new ComplexFloatMatrix(rows);
+
+ for (int r = 0; r < rows; r++)
+ v.put(r, getRow(r).sum());
+
+ return v;
+ }
+
+ public ComplexFloatMatrix rowMeans() {
+ return rowSums().divi(columns);
+ }
+
+ public ComplexFloatMatrix getColumn(int c) {
+ ComplexFloatMatrix result = new ComplexFloatMatrix(rows, 1);
+ Blas.ccopy(rows, data, index(0, c), 1, result.data, 0, 1);
+ return result;
+ }
+
+ public void putColumn(int c, ComplexFloatMatrix v) {
+ Blas.ccopy(rows, v.data, 0, 1, data, index(0, c), 1);
+ }
+
+ public ComplexFloatMatrix getRow(int r) {
+ ComplexFloatMatrix result = new ComplexFloatMatrix(1, columns);
+ Blas.ccopy(columns, data, index(r, 0), rows, result.data, 0, 1);
+ return result;
+ }
+
+ public void putRow(int r, ComplexFloatMatrix v) {
+ Blas.ccopy(columns, v.data, 0, 1, data, index(r, 0), rows);
+ }
+
+ /**************************************************************************
+ * Elementwise Functions
+ */
+
+ /** Add a row vector to all rows of the matrix */
+ public void addRowVector(ComplexFloatMatrix x) {
+ for (int r = 0; r < rows; r++) {
+ Blas.caxpy(columns, ComplexFloat.UNIT, x.data, 0, 1, data, index(r, 0), rows);
+ }
+ }
+
+ /** Add a vector to all columns of the matrix */
+ public void addColumnVector(ComplexFloatMatrix x) {
+ for (int c = 0; c < columns; c++) {
+ Blas.caxpy(rows, ComplexFloat.UNIT, x.data, 0, 1, data, index(0, c), 1);
+ }
+ }
+
+ /** Add a row vector to all rows of the matrix */
+ public void subRowVector(ComplexFloatMatrix x) {
+ for (int r = 0; r < rows; r++) {
+ Blas.caxpy(columns, ComplexFloat.NEG_UNIT, x.data, 0, 1, data, index(r, 0), rows);
+ }
+ }
+
+ /** Add a vector to all columns of the matrix */
+ public void subColumnVector(ComplexFloatMatrix x) {
+ for (int c = 0; c < columns; c++) {
+ Blas.caxpy(rows, ComplexFloat.NEG_UNIT, x.data, 0, 1, data, index(0, c), 1);
+ }
+ }
+
+ /**
+ * Writes out this matrix to the given data stream.
+ * @param dos the data output stream to write to.
+ * @throws IOException
+ */
+ public void out(DataOutputStream dos) throws IOException {
+ dos.writeUTF("float");
+ dos.writeInt(columns);
+ dos.writeInt(rows);
+
+ dos.writeInt(data.length);
+ for(int i=0; i < data.length;i++)
+ dos.writeDouble(data[i]);
+ }
+
+ /**
+ * Reads in a matrix from the given data stream. Note
+ * that the old data of this matrix will be discarded.
+ * @param dis the data input stream to read from.
+ * @throws IOException
+ */
+ public void in(DataInputStream dis) throws IOException {
+ if(!dis.readUTF().equals("float"))
+ throw new IllegalStateException("The matrix in the specified file is not of the correct type!");
+
+ this.columns = dis.readInt();
+ this.rows = dis.readInt();
+
+ final int MAX = dis.readInt();
+ data = new float[MAX];
+ for(int i=0; i < MAX;i++)
+ data[i] = dis.readFloat();
+ }
+
+ /**
+ * Saves this matrix to the specified file.
+ * @param filename the file to write the matrix in.
+ * @throws IOException thrown on errors while writing the matrix to the file
+ */
+ public void save(String filename) throws IOException {
+ DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename, false));
+ this.out(dos);
+ }
+
+ /**
+ * Loads a matrix from a file into this matrix. Note that the old data
+ * of this matrix will be discarded.
+ * @param filename the file to read the matrix from
+ * @throws IOException thrown on errors while reading the matrix
+ */
+ public void load(String filename) throws IOException {
+ DataInputStream dis = new DataInputStream(new FileInputStream(filename));
+ this.in(dis);
+ }
+
+ /****************************************************************
+ * Autogenerated code
+ */
+
+ /***** Code for operators ***************************************/
+
+ /* Overloads for the usual arithmetic operations */
+ /*#
+ def gen_overloads(base, result_rows, result_cols); <<-EOS
+ public ComplexFloatMatrix #{base}i(ComplexFloatMatrix other) {
+ return #{base}i(other, this);
+ }
+
+ public ComplexFloatMatrix #{base}(ComplexFloatMatrix other) {
+ return #{base}i(other, new ComplexFloatMatrix(#{result_rows}, #{result_cols}));
+ }
+
+ public ComplexFloatMatrix #{base}i(ComplexFloat v) {
+ return #{base}i(v, this);
+ }
+
+ public ComplexFloatMatrix #{base}i(float v) {
+ return #{base}i(new ComplexFloat(v), this);
+ }
+
+ public ComplexFloatMatrix #{base}(ComplexFloat v) {
+ return #{base}i(v, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix #{base}(float v) {
+ return #{base}i(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
+ }
+
+ EOS
+ end
+ #*/
+
+ /* Generating code for logical operators. This not only generates the stubs
+ * but really all of the code.
+ */
+
+ /*#
+ def gen_compare(name, op); <<-EOS
+ public ComplexFloatMatrix #{name}i(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return #{name}i(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat c1 = new ComplexFloat(0.0f);
+ ComplexFloat c2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c1).#{op}(other.get(i, c2)) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix #{name}i(ComplexFloatMatrix other) {
+ return #{name}i(other, this);
+ }
+
+ public ComplexFloatMatrix #{name}(ComplexFloatMatrix other) {
+ return #{name}i(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix #{name}i(ComplexFloat value, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+ ComplexFloat c = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).#{op}(value) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix #{name}i(float value, ComplexFloatMatrix result) {
+ return #{name}i(new ComplexFloat(value), result);
+ }
+
+ public ComplexFloatMatrix #{name}i(ComplexFloat value) {
+ return #{name}i(value, this);
+ }
+
+ public ComplexFloatMatrix #{name}i(float value) {
+ return #{name}i(new ComplexFloat(value));
+ }
+
+ public ComplexFloatMatrix #{name}(ComplexFloat value) {
+ return #{name}i(value, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix #{name}(float value) {
+ return #{name}i(new ComplexFloat(value));
+ }
+
+ EOS
+ end
+ #*/
+
+ /*#
+ def gen_logical(name, op); <<-EOS
+ public ComplexFloatMatrix #{name}i(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat t1 = new ComplexFloat(0.0f);
+ ComplexFloat t2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (!get(i, t1).isZero()) #{op} (!other.get(i, t2).isZero()) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix #{name}i(ComplexFloatMatrix other) {
+ return #{name}i(other, this);
+ }
+
+ public ComplexFloatMatrix #{name}(ComplexFloatMatrix other) {
+ return #{name}i(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix #{name}i(ComplexFloat value, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = !value.isZero();
+ ComplexFloat t = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, !get(i, t).isZero() #{op} val ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix #{name}i(float value, ComplexFloatMatrix result) {
+ return #{name}i(new ComplexFloat(value), result);
+ }
+
+ public ComplexFloatMatrix #{name}i(ComplexFloat value) {
+ return #{name}i(value, this);
+ }
+
+ public ComplexFloatMatrix #{name}i(float value) {
+ return #{name}i(new ComplexFloat(value), this);
+ }
+
+ public ComplexFloatMatrix #{name}(ComplexFloat value) {
+ return #{name}i(value, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix #{name}(float value) {
+ return #{name}i(new ComplexFloat(value));
+ }
+ EOS
+ end
+ #*/
+
+ /*# collect(gen_overloads('add', 'rows', 'columns'),
+ gen_overloads('sub', 'rows', 'columns'),
+ gen_overloads('rsub', 'rows', 'columns'),
+ gen_overloads('div', 'rows', 'columns'),
+ gen_overloads('rdiv', 'rows', 'columns'),
+ gen_overloads('mul', 'rows', 'columns'),
+ gen_overloads('mmul', 'rows', 'other.columns'),
+ gen_compare('eq', 'eq'),
+ gen_compare('ne', 'eq'),
+ gen_logical('and', '&'),
+ gen_logical('or', '|'),
+ gen_logical('xor', '^'))
+ #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public ComplexFloatMatrix addi(ComplexFloatMatrix other) {
+ return addi(other, this);
+ }
+
+ public ComplexFloatMatrix add(ComplexFloatMatrix other) {
+ return addi(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix addi(ComplexFloat v) {
+ return addi(v, this);
+ }
+
+ public ComplexFloatMatrix addi(float v) {
+ return addi(new ComplexFloat(v), this);
+ }
+
+ public ComplexFloatMatrix add(ComplexFloat v) {
+ return addi(v, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix add(float v) {
+ return addi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
+ }
+
+
+ public ComplexFloatMatrix subi(ComplexFloatMatrix other) {
+ return subi(other, this);
+ }
+
+ public ComplexFloatMatrix sub(ComplexFloatMatrix other) {
+ return subi(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix subi(ComplexFloat v) {
+ return subi(v, this);
+ }
+
+ public ComplexFloatMatrix subi(float v) {
+ return subi(new ComplexFloat(v), this);
+ }
+
+ public ComplexFloatMatrix sub(ComplexFloat v) {
+ return subi(v, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix sub(float v) {
+ return subi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
+ }
+
+
+ public ComplexFloatMatrix rsubi(ComplexFloatMatrix other) {
+ return rsubi(other, this);
+ }
+
+ public ComplexFloatMatrix rsub(ComplexFloatMatrix other) {
+ return rsubi(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix rsubi(ComplexFloat v) {
+ return rsubi(v, this);
+ }
+
+ public ComplexFloatMatrix rsubi(float v) {
+ return rsubi(new ComplexFloat(v), this);
+ }
+
+ public ComplexFloatMatrix rsub(ComplexFloat v) {
+ return rsubi(v, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix rsub(float v) {
+ return rsubi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
+ }
+
+
+ public ComplexFloatMatrix divi(ComplexFloatMatrix other) {
+ return divi(other, this);
+ }
+
+ public ComplexFloatMatrix div(ComplexFloatMatrix other) {
+ return divi(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix divi(ComplexFloat v) {
+ return divi(v, this);
+ }
+
+ public ComplexFloatMatrix divi(float v) {
+ return divi(new ComplexFloat(v), this);
+ }
+
+ public ComplexFloatMatrix div(ComplexFloat v) {
+ return divi(v, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix div(float v) {
+ return divi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
+ }
+
+
+ public ComplexFloatMatrix rdivi(ComplexFloatMatrix other) {
+ return rdivi(other, this);
+ }
+
+ public ComplexFloatMatrix rdiv(ComplexFloatMatrix other) {
+ return rdivi(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix rdivi(ComplexFloat v) {
+ return rdivi(v, this);
+ }
+
+ public ComplexFloatMatrix rdivi(float v) {
+ return rdivi(new ComplexFloat(v), this);
+ }
+
+ public ComplexFloatMatrix rdiv(ComplexFloat v) {
+ return rdivi(v, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix rdiv(float v) {
+ return rdivi(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
+ }
+
+
+ public ComplexFloatMatrix muli(ComplexFloatMatrix other) {
+ return muli(other, this);
+ }
+
+ public ComplexFloatMatrix mul(ComplexFloatMatrix other) {
+ return muli(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix muli(ComplexFloat v) {
+ return muli(v, this);
+ }
+
+ public ComplexFloatMatrix muli(float v) {
+ return muli(new ComplexFloat(v), this);
+ }
+
+ public ComplexFloatMatrix mul(ComplexFloat v) {
+ return muli(v, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix mul(float v) {
+ return muli(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
+ }
+
+
+ public ComplexFloatMatrix mmuli(ComplexFloatMatrix other) {
+ return mmuli(other, this);
+ }
+
+ public ComplexFloatMatrix mmul(ComplexFloatMatrix other) {
+ return mmuli(other, new ComplexFloatMatrix(rows, other.columns));
+ }
+
+ public ComplexFloatMatrix mmuli(ComplexFloat v) {
+ return mmuli(v, this);
+ }
+
+ public ComplexFloatMatrix mmuli(float v) {
+ return mmuli(new ComplexFloat(v), this);
+ }
+
+ public ComplexFloatMatrix mmul(ComplexFloat v) {
+ return mmuli(v, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix mmul(float v) {
+ return mmuli(new ComplexFloat(v), new ComplexFloatMatrix(rows, columns));
+ }
+
+
+ public ComplexFloatMatrix eqi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return eqi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat c1 = new ComplexFloat(0.0f);
+ ComplexFloat c2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c1).eq(other.get(i, c2)) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix eqi(ComplexFloatMatrix other) {
+ return eqi(other, this);
+ }
+
+ public ComplexFloatMatrix eq(ComplexFloatMatrix other) {
+ return eqi(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix eqi(ComplexFloat value, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+ ComplexFloat c = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).eq(value) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix eqi(float value, ComplexFloatMatrix result) {
+ return eqi(new ComplexFloat(value), result);
+ }
+
+ public ComplexFloatMatrix eqi(ComplexFloat value) {
+ return eqi(value, this);
+ }
+
+ public ComplexFloatMatrix eqi(float value) {
+ return eqi(new ComplexFloat(value));
+ }
+
+ public ComplexFloatMatrix eq(ComplexFloat value) {
+ return eqi(value, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix eq(float value) {
+ return eqi(new ComplexFloat(value));
+ }
+
+
+ public ComplexFloatMatrix nei(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ if (other.isScalar())
+ return nei(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat c1 = new ComplexFloat(0.0f);
+ ComplexFloat c2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c1).eq(other.get(i, c2)) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix nei(ComplexFloatMatrix other) {
+ return nei(other, this);
+ }
+
+ public ComplexFloatMatrix ne(ComplexFloatMatrix other) {
+ return nei(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix nei(ComplexFloat value, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+ ComplexFloat c = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i, c).eq(value) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix nei(float value, ComplexFloatMatrix result) {
+ return nei(new ComplexFloat(value), result);
+ }
+
+ public ComplexFloatMatrix nei(ComplexFloat value) {
+ return nei(value, this);
+ }
+
+ public ComplexFloatMatrix nei(float value) {
+ return nei(new ComplexFloat(value));
+ }
+
+ public ComplexFloatMatrix ne(ComplexFloat value) {
+ return nei(value, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix ne(float value) {
+ return nei(new ComplexFloat(value));
+ }
+
+
+ public ComplexFloatMatrix andi(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat t1 = new ComplexFloat(0.0f);
+ ComplexFloat t2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (!get(i, t1).isZero()) & (!other.get(i, t2).isZero()) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix andi(ComplexFloatMatrix other) {
+ return andi(other, this);
+ }
+
+ public ComplexFloatMatrix and(ComplexFloatMatrix other) {
+ return andi(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix andi(ComplexFloat value, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = !value.isZero();
+ ComplexFloat t = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, !get(i, t).isZero() & val ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix andi(float value, ComplexFloatMatrix result) {
+ return andi(new ComplexFloat(value), result);
+ }
+
+ public ComplexFloatMatrix andi(ComplexFloat value) {
+ return andi(value, this);
+ }
+
+ public ComplexFloatMatrix andi(float value) {
+ return andi(new ComplexFloat(value), this);
+ }
+
+ public ComplexFloatMatrix and(ComplexFloat value) {
+ return andi(value, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix and(float value) {
+ return andi(new ComplexFloat(value));
+ }
+
+ public ComplexFloatMatrix ori(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat t1 = new ComplexFloat(0.0f);
+ ComplexFloat t2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (!get(i, t1).isZero()) | (!other.get(i, t2).isZero()) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix ori(ComplexFloatMatrix other) {
+ return ori(other, this);
+ }
+
+ public ComplexFloatMatrix or(ComplexFloatMatrix other) {
+ return ori(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix ori(ComplexFloat value, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = !value.isZero();
+ ComplexFloat t = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, !get(i, t).isZero() | val ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix ori(float value, ComplexFloatMatrix result) {
+ return ori(new ComplexFloat(value), result);
+ }
+
+ public ComplexFloatMatrix ori(ComplexFloat value) {
+ return ori(value, this);
+ }
+
+ public ComplexFloatMatrix ori(float value) {
+ return ori(new ComplexFloat(value), this);
+ }
+
+ public ComplexFloatMatrix or(ComplexFloat value) {
+ return ori(value, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix or(float value) {
+ return ori(new ComplexFloat(value));
+ }
+
+ public ComplexFloatMatrix xori(ComplexFloatMatrix other, ComplexFloatMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ ComplexFloat t1 = new ComplexFloat(0.0f);
+ ComplexFloat t2 = new ComplexFloat(0.0f);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (!get(i, t1).isZero()) ^ (!other.get(i, t2).isZero()) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix xori(ComplexFloatMatrix other) {
+ return xori(other, this);
+ }
+
+ public ComplexFloatMatrix xor(ComplexFloatMatrix other) {
+ return xori(other, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix xori(ComplexFloat value, ComplexFloatMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = !value.isZero();
+ ComplexFloat t = new ComplexFloat(0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, !get(i, t).isZero() ^ val ? 1.0f : 0.0f);
+ return result;
+ }
+
+ public ComplexFloatMatrix xori(float value, ComplexFloatMatrix result) {
+ return xori(new ComplexFloat(value), result);
+ }
+
+ public ComplexFloatMatrix xori(ComplexFloat value) {
+ return xori(value, this);
+ }
+
+ public ComplexFloatMatrix xori(float value) {
+ return xori(new ComplexFloat(value), this);
+ }
+
+ public ComplexFloatMatrix xor(ComplexFloat value) {
+ return xori(value, new ComplexFloatMatrix(rows, columns));
+ }
+
+ public ComplexFloatMatrix xor(float value) {
+ return xori(new ComplexFloat(value));
+ }
+//RJPP-END--------------------------------------------------------------
+}
diff --git a/src/org/jblas/la/DoubleFunction.java b/src/org/jblas/la/DoubleFunction.java
new file mode 100644
index 0000000..fc6d54e
--- /dev/null
+++ b/src/org/jblas/la/DoubleFunction.java
@@ -0,0 +1,45 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+/**
+ * Represents a function on doubles.
+ */
+public interface DoubleFunction {
+ /** Compute the function. */
+ public double compute(double x);
+}
diff --git a/src/org/jblas/la/DoubleMatrix.java b/src/org/jblas/la/DoubleMatrix.java
new file mode 100644
index 0000000..33b1b48
--- /dev/null
+++ b/src/org/jblas/la/DoubleMatrix.java
@@ -0,0 +1,2965 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * Copyright (c) 2008, Johannes Schaback
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.exceptions.SizeException;
+import org.jblas.la.ranges.Range;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * A general matrix class for <tt>double</tt> typed values.
+ *
+ * Don't be intimidated by the large number of methods this function defines. Most
+ * are overloads provided for ease of use. For example, for each arithmetic operation,
+ * up to six overloaded versions exist to handle in-place computations, and
+ * scalar arguments.
+ *
+ * <h3>Construction</h3>
+ *
+ * <p>To construct a two-dimensional matrices, you can use the following constructors
+ * and static methods.</p>
+ *
+ * <table class="my">
+ * <tr><th>Method<th>Description
+ * <tr><td>DoubleMatrix(m,n, [value1, value2, value3...])<td>Values are filled in row by row.
+ * <tr><td>DoubleMatrix(new double[][] {{value1, value2, ...}, ...}<td>Inner arrays are columns.
+ * <tr><td>DoubleMatrix.zeros(m,n) <td>Initial values set to 0.0.
+ * <tr><td>DoubleMatrix.ones(m,n) <td>Initial values set to 1.0.
+ * <tr><td>DoubleMatrix.rand(m,n) <td>Values drawn at random between 0.0 and 1.0.
+ * <tr><td>DoubleMatrix.randn(m,n) <td>Values drawn from normal distribution.
+ * <tr><td>DoubleMatrix.eye(n) <td>Unit matrix (values 0.0 except for 1.0 on the diagonal).
+ * <tr><td>DoubleMatrix.diag(array) <td>Diagonal matrix with given diagonal elements.
+ * </table>
+ *
+ * <p>Alternatively, you can construct (column) vectors, if you just supply the length
+ * using the following constructors and static methods.</p>
+ *
+ * <table class="my">
+ * <tr><th>Method<th>Description
+ * <tr><td>DoubleMatrix(m)<td>Constructs a column vector.
+ * <tr><td>DoubleMatrix(new double[] {value1, value2, ...})<td>Constructs a column vector.
+ * <tr><td>DoubleMatrix.zeros(m) <td>Initial values set to 1.0.
+ * <tr><td>DoubleMatrix.ones(m) <td>Initial values set to 0.0.
+ * <tr><td>DoubleMatrix.rand(m) <td>Values drawn at random between 0.0 and 1.0.
+ * <tr><td>DoubleMatrix.randn(m) <td>Values drawn from normal distribution.
+ * </table>
+ *
+ * <p>You can also construct new matrices by concatenating matrices either horziontally
+ * or vertically:</p>
+ *
+ * <table class="my">
+ * <tr><th>Method<th>Description
+ * <tr><td>x.concatHorizontally(y)<td>New matrix will be x next to y.
+ * <tr><td>x.concatVertically(y)<td>New matrix will be x atop y.
+ * </table>
+ *
+ * <h3>Element Access, Copying and Duplication</h3>
+ *
+ * <p>To access individual elements, or whole rows and columns, use the following
+ * methods:<p>
+ *
+ * <table class="my">
+ * <tr><th>x.Method<th>Description
+ * <tr><td>x.get(i,j)<td>Get element in row i and column j.
+ * <tr><td>x.put(i, j, v)<td>Set element in row i and column j to value v
+ * <tr><td>x.get(i)<td>Get the ith element of the matrix (traversing rows first).
+ * <tr><td>x.put(i, v)<td>Set the ith element of the matrix (traversing rows first).
+ * <tr><td>x.getColumn(i)<td>Get a copy of column i.
+ * <tr><td>x.putColumn(i, c)<td>Put matrix c into column i.
+ * <tr><td>x.getRow(i)<td>Get a copy of row i.
+ * <tr><td>x.putRow(i, c)<td>Put matrix c into row i.
+ * <tr><td>x.swapColumns(i, j)<td>Swap the contents of columns i and j.
+ * <tr><td>x.swapRows(i, j)<td>Swap the contents of columns i and j.
+ * </table>
+ *
+ * <p>For <tt>get</tt> and <tt>put</tt>, you can also pass integer arrays,
+ * DoubleMatrix objects, or Range objects, which then specify the indices used
+ * as follows:
+ *
+ * <ul>
+ * <li><em>integer array:</em> the elements will be used as indices.
+ * <li><em>DoubleMatrix object:</em> non-zero entries specify the indices.
+ * <li><em>Range object:</em> see below.
+ * </ul>
+ *
+ * <p>When using <tt>put</tt> with multiple indices, the assigned object must
+ * have the correct size or be a scalar.</p>
+ *
+ * <p>There exist the following Range objects. The Class <tt>RangeUtils</tt> also
+ * contains the a number of handy helper methods for constructing these ranges.</p>
+ * <table class="my">
+ * <tr><th>Class <th>RangeUtils method <th>Indices
+ * <tr><td>AllRange <td>all() <td>All legal indices.
+ * <tr><td>PointRange <td>point(i) <td> A single point.
+ * <tr><td>IntervalRange <td>interval(a, b)<td> All indices from a to b (inclusive)
+ * <tr><td rowspan=3>IndicesRange <td>indices(int[])<td> The specified indices.
+ * <tr><td>indices(DoubleMatrix)<td>The specified indices.
+ * <tr><td>find(DoubleMatrix)<td>The non-zero entries of the matrix.
+ * </table>
+ *
+ * <p>The following methods can be used for duplicating and copying matrices.</p>
+ *
+ * <table class="my">
+ * <tr><th>Method<th>Description
+ * <tr><td>x.dup()<td>Get a copy of x.
+ * <tr><td>x.copy(y)<td>Copy the contents of y to x (possible resizing x).
+ * </table>
+ *
+ * <h3>Size and Shape</h3>
+ *
+ * <p>The following methods permit to acces the size of a matrix and change its size or shape.</p>
+ *
+ * <table class="my">
+ * <tr><th>x.Method<th>Description
+ * <tr><td>x.rows<td>Number of rows.
+ * <tr><td>x.columns<td>Number of columns.
+ * <tr><td>x.length<td>Total number of elements.
+ * <tr><td>x.isEmpty()<td>Checks whether rows == 0 and columns == 0.
+ * <tr><td>x.isRowVector()<td>Checks whether rows == 1.
+ * <tr><td>x.isColumnVector()<td>Checks whether columns == 1.
+ * <tr><td>x.isVector()<td>Checks whether rows == 1 or columns == 1.
+ * <tr><td>x.isSquare()<td>Checks whether rows == columns.
+ * <tr><td>x.isScalar()<td>Checks whether length == 1.
+ * <tr><td>x.resize(r, c)<td>Resize the matrix to r rows and c columns, discarding the content.
+ * <tr><td>x.reshape(r, c)<td>Resize the matrix to r rows and c columns.<br> Number of elements must not change.
+ * </table>
+ *
+ * <p>The size is stored in the <tt>rows</tt> and <tt>columns</tt> member variables.
+ * The total number of elements is stored in <tt>length</tt>. Do not change these
+ * values unless you know what you're doing!</p>
+ *
+ * <h3>Arithmetics</h3>
+ *
+ * <p>The usual arithmetic operations are implemented. Each operation exists in a
+ * in-place version, recognizable by the suffix <tt>"i"</tt>, to which you can supply
+ * the result matrix (or <tt>this</tt> is used, if missing). Using in-place operations
+ * can also lead to a smaller memory footprint, as the number of temporary objects
+ * which are directly garbage collected again is reduced.</p>
+ *
+ * <p>Whenever you specify a result vector, the result vector must already have the
+ * correct dimensions.</p>
+ *
+ * <p>For example, you can add two matrices using the <tt>add</tt> method. If you want
+ * to store the result in of <tt>x + y</tt> in <tt>z</tt>, type
+ * <span class=code>
+ * x.addi(y, z) // computes x = y + z.
+ * </span>
+ * Even in-place methods return the result, such that you can easily chain in-place methods,
+ * for example:
+ * <span class=code>
+ * x.addi(y).addi(z) // computes x += y; x += z
+ * </span></p>
+ *
+ * <p>Methods which operate element-wise only make sure that the length of the matrices
+ * is correct. Therefore, you can add a 3 * 3 matrix to a 1 * 9 matrix, for example.</p>
+ *
+ * <p>Finally, there exist versions which take doubles instead of DoubleMatrix Objects
+ * as arguments. These then compute the operation with the same value as the
+ * right-hand-side. The same effect can be achieved by passing a DoubleMatrix with
+ * exactly one element.</p>
+ *
+ * <table class="my">
+ * <tr><th>Operation <th>Method <th>Comment
+ * <tr><td>x + y <td>x.add(y) <td>
+ * <tr><td>x - y <td>x.sub(y), y.rsub(x) <td>rsub subtracts left from right hand side
+ * <tr><td rowspan=3>x * y <td>x.mul(y) <td>element-wise multiplication
+ * <tr> <td>x.mmul(y)<td>matrix-matrix multiplication
+ * <tr> <td>x.dot(y) <td>scalar-product
+ * <tr><td>x / y <td>x.div(y), y.rdiv(x) <td>rdiv divides right hand side by left hand side.
+ * <tr><td>- x <td>x.neg() <td>
+ * </table>
+ *
+ * <p>There also exist operations which work on whole columns or rows.</p>
+ *
+ * <table class="my">
+ * <tr><th>Method <th>Description
+ * <tr><td>x.addRowVector<td>adds a vector to each row (addiRowVector works in-place)
+ * <tr><td>x.addColumnVector<td>adds a vector to each column
+ * <tr><td>x.subRowVector<td>subtracts a vector from each row
+ * <tr><td>x.subColumnVector<td>subtracts a vector from each column
+ * <tr><td>x.mulRow<td>Multiplies a row by a scalar
+ * <tr><td>x.mulColumn<td>multiplies a row by a column
+ * </table>
+ *
+ * <p>In principle, you could achieve the same result by first calling getColumn(),
+ * adding, and then calling putColumn, but these methods are much faster.</p>
+ *
+ * <p>The following comparison operations are available</p>
+ *
+ * <table class="my">
+ * <tr><th>Operation <th>Method
+ * <tr><td>x < y <td>x.lt(y)
+ * <tr><td>x <= y <td>x.le(y)
+ * <tr><td>x > y <td>x.gt(y)
+ * <tr><td>x >= y <td>x.ge(y)
+ * <tr><td>x == y <td>x.eq(y)
+ * <tr><td>x != y <td>x.ne(y)
+ * </table>
+ *
+ * <p> Logical operations are also supported. For these operations, a value different from
+ * zero is treated as "true" and zero is treated as "false". All operations are carried
+ * out elementwise.</p>
+ *
+ * <table class="my">
+ * <tr><th>Operation <th>Method
+ * <tr><td>x & y <td>x.and(y)
+ * <tr><td>x | y <td>x.or(y)
+ * <tr><td>x ^ y <td>x.xor(y)
+ * <tr><td>! x <td>x.not()
+ * </table>
+ *
+ * <p>Finally, there are a few more methods to compute various things:</p>
+ *
+ * <table class="my">
+ * <tr><th>Method <th>Description
+ * <tr><td>x.max() <td>Return maximal element
+ * <tr><td>x.argmax() <td>Return index of largest element
+ * <tr><td>x.min() <td>Return minimal element
+ * <tr><td>x.argmin() <td>Return index of largest element
+ * <tr><td>x.columnMins() <td>Return column-wise minima
+ * <tr><td>x.columnArgmins() <td>Return column-wise index of minima
+ * <tr><td>x.columnMaxs() <td>Return column-wise maxima
+ * <tr><td>x.columnArgmaxs() <td>Return column-wise index of maxima
+ * </table>
+ *
+ * @author Mikio Braun, Johannes Schaback
+ */
+public class DoubleMatrix {
+
+ /** Number of rows. */
+ public int rows;
+ /** Number of columns. */
+ public int columns;
+ /** Total number of elements (for convenience). */
+ public int length;
+ /** The actual data stored by rows (that is, row 0, row 1...). */
+ public double[] data = null; // rows are contiguous
+ public static final DoubleMatrix EMPTY = new DoubleMatrix();
+
+ /**************************************************************************
+ *
+ * Constructors and factory functions
+ *
+ **************************************************************************/
+ /** Create a new matrix with <i>newRows</i> rows, <i>newColumns</i> columns
+ * using <i>newData></i> as the data. The length of the data is not checked!
+ */
+ public DoubleMatrix(int newRows, int newColumns, double... newData) {
+ rows = newRows;
+ columns = newColumns;
+ length = rows * columns;
+
+ if (newData != null && newData.length != newRows * newColumns) {
+ throw new IllegalArgumentException(
+ "Passed data must match matrix dimensions.");
+ }
+
+ data = newData;
+ //System.err.printf("%d * %d matrix created\n", rows, columns);
+ }
+
+ /**
+ * Creates a new <i>n</i> times <i>m</i> <tt>DoubleMatrix</tt>.
+ * @param newRows the number of rows (<i>n</i>) of the new matrix.
+ * @param newColumns the number of columns (<i>m</i>) of the new matrix.
+ */
+ public DoubleMatrix(int newRows, int newColumns) {
+ this(newRows, newColumns, new double[newRows * newColumns]);
+ }
+
+ /**
+ * Creates a new <tt>DoubleMatrix</tt> of size 0 times 0.
+ */
+ public DoubleMatrix() {
+ this(0, 0, (double[]) null);
+ }
+
+ /**
+ * Create a Matrix of length <tt>len</tt>. By default, this creates a row vector.
+ * @param len
+ */
+ public DoubleMatrix(int len) {
+ this(len, 1, new double[len]);
+ }
+
+ public DoubleMatrix(double[] newData) {
+ this(newData.length);
+ data = newData;
+ }
+
+ /**
+ * Creates a new matrix by reading it from a file.
+ * @param filename the path and name of the file to read the matrix from
+ * @throws IOException
+ */
+ public DoubleMatrix(String filename) throws IOException {
+ load(filename);
+ }
+
+ /**
+ * Creates a new <i>n</i> times <i>m</i> <tt>DoubleMatrix</tt> from
+ * the given <i>n</i> times <i>m</i> 2D data array. The first dimension of the array makes the
+ * rows (<i>n</i>) and the second dimension the columns (<i>m</i>). For example, the
+ * given code <br/><br/>
+ * <code>new DoubleMatrix(new double[][]{{1d, 2d, 3d}, {4d, 5d, 6d}, {7d, 8d, 9d}}).print();</code><br/><br/>
+ * will constructs the following matrix:
+ * <pre>
+ * 1.0 2.0 3.0
+ * 4.0 5.0 6.0
+ * 7.0 8.0 9.0
+ * </pre>.
+ * @param data <i>n</i> times <i>m</i> data array
+ */
+ public DoubleMatrix(double[][] data) {
+ this(data.length, data[0].length);
+
+ for (int r = 0; r < rows; r++) {
+ assert (data[r].length == columns);
+ }
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ put(r, c, data[r][c]);
+ }
+ }
+ }
+
+ /** Create matrix with random values uniformly in 0..1. */
+ public static DoubleMatrix rand(int rows, int columns) {
+ DoubleMatrix m = new DoubleMatrix(rows, columns);
+
+ java.util.Random r = new java.util.Random();
+ for (int i = 0; i < rows * columns; i++) {
+ m.data[i] = r.nextDouble();
+ }
+
+ return m;
+ }
+
+ /** Creates a row vector with random values uniformly in 0..1. */
+ public static DoubleMatrix rand(int len) {
+ return rand(len, 1);
+ }
+
+ /** Create matrix with normally distributed random values. */
+ public static DoubleMatrix randn(int rows, int columns) {
+ DoubleMatrix m = new DoubleMatrix(rows, columns);
+
+ java.util.Random r = new java.util.Random();
+ for (int i = 0; i < rows * columns; i++) {
+ m.data[i] = (double) r.nextGaussian();
+ }
+
+ return m;
+ }
+
+ /** Create row vector with normally distributed random values. */
+ public static DoubleMatrix randn(int len) {
+ return randn(len, 1);
+ }
+
+ /** Creates a new matrix in which all values are equal 0. */
+ public static DoubleMatrix zeros(int rows, int columns) {
+ return new DoubleMatrix(rows, columns);
+ }
+
+ /** Creates a row vector of given length. */
+ public static DoubleMatrix zeros(int length) {
+ return zeros(length, 1);
+ }
+
+ /** Creates a new matrix in which all values are equal 1. */
+ public static DoubleMatrix ones(int rows, int columns) {
+ DoubleMatrix m = new DoubleMatrix(rows, columns);
+
+ for (int i = 0; i < rows * columns; i++) {
+ m.put(i, 1.0);
+ }
+
+ return m;
+ }
+
+ /** Creates a row vector with all elements equal to 1. */
+ public static DoubleMatrix ones(int length) {
+ return ones(length, 1);
+ }
+
+ /** Construct a new n-by-n identity matrix. */
+ public static DoubleMatrix eye(int n) {
+ DoubleMatrix m = new DoubleMatrix(n, n);
+
+ for (int i = 0; i < n; i++) {
+ m.put(i, i, 1.0);
+ }
+
+ return m;
+ }
+
+ /**
+ * Creates a new matrix where the values of the given vector are the diagonal values of
+ * the matrix.
+ */
+ public static DoubleMatrix diag(DoubleMatrix x) {
+ DoubleMatrix m = new DoubleMatrix(x.length, x.length);
+
+ for (int i = 0; i < x.length; i++) {
+ m.put(i, i, x.get(i));
+ }
+
+ return m;
+ }
+
+ /**
+ * Create a 1-by-1 matrix. For many operations, this matrix functions like a
+ * normal double.
+ */
+ public static DoubleMatrix scalar(double s) {
+ DoubleMatrix m = new DoubleMatrix(1, 1);
+ m.put(0, 0, s);
+ return m;
+ }
+
+ /** Test whether a matrix is scalar. */
+ public boolean isScalar() {
+ return length == 1;
+ }
+
+ /** Return the first element of the matrix. */
+ public double scalar() {
+ return get(0);
+ }
+
+ /**
+ * Concatenates two matrices horizontally. Matrices must have identical
+ * numbers of rows.
+ */
+ public static DoubleMatrix concatHorizontally(DoubleMatrix A, DoubleMatrix B) {
+ if (A.rows != B.rows) {
+ throw new SizeException("Matrices don't have same number of rows.");
+ }
+
+ DoubleMatrix result = new DoubleMatrix(A.rows, A.columns + B.columns);
+ SimpleBlas.copy(A, result);
+ JavaBlas.rcopy(B.length, B.data, 0, 1, result.data, A.length, 1);
+ return result;
+ }
+
+ /**
+ * Concatenates two matrices vertically. Matrices must have identical
+ * numbers of columns.
+ */
+ public static DoubleMatrix concatVertically(DoubleMatrix A, DoubleMatrix B) {
+ if (A.columns != B.columns) {
+ throw new SizeException("Matrices don't have same number of columns (" + A.columns + " != " + B.columns + ".");
+ }
+
+ DoubleMatrix result = new DoubleMatrix(A.rows + B.rows, A.columns);
+
+ for (int i = 0; i < A.columns; i++) {
+ JavaBlas.rcopy(A.rows, A.data, A.index(0, i), 1, result.data, result.index(0, i), 1);
+ JavaBlas.rcopy(B.rows, B.data, B.index(0, i), 1, result.data, result.index(A.rows, i), 1);
+ }
+
+ return result;
+ }
+
+ /**************************************************************************
+ * Working with slices (Man! 30+ methods just to make this a bit flexible...)
+ */
+ /** Get all elements specified by the linear indices. */
+ public DoubleMatrix get(int[] indices) {
+ DoubleMatrix result = new DoubleMatrix(indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ result.put(i, get(indices[i]));
+ }
+
+ return result;
+ }
+
+ /** Get all elements for a given row and the specified columns. */
+ public DoubleMatrix get(int r, int[] indices) {
+ DoubleMatrix result = new DoubleMatrix(1, indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ result.put(i, get(r, indices[i]));
+ }
+
+ return result;
+ }
+
+ /** Get all elements for a given column and the specified rows. */
+ public DoubleMatrix get(int[] indices, int c) {
+ DoubleMatrix result = new DoubleMatrix(indices.length, c);
+
+ for (int i = 0; i < indices.length; i++) {
+ result.put(i, get(indices[i], c));
+ }
+
+ return result;
+ }
+
+ /** Get all elements from the specified rows and columns. */
+ public DoubleMatrix get(int[] rindices, int[] cindices) {
+ DoubleMatrix result = new DoubleMatrix(rindices.length, cindices.length);
+
+ for (int i = 0; i < rindices.length; i++) {
+ for (int j = 0; j < cindices.length; j++) {
+ result.put(i, j, get(rindices[i], cindices[j]));
+ }
+ }
+
+ return result;
+ }
+
+ /** Get elements from specified rows and columns. */
+ public DoubleMatrix get(Range rs, Range cs) {
+ rs.init(0, rows - 1);
+ cs.init(0, columns - 1);
+ DoubleMatrix result = new DoubleMatrix(rs.length(), cs.length());
+
+ for (; !rs.hasMore(); rs.next()) {
+ for (; !cs.hasMore(); cs.next()) {
+ result.put(rs.index(), cs.index(), get(rs.value(), cs.value()));
+ }
+ }
+
+ return result;
+ }
+
+ /** Get elements specified by the non-zero entries of the passed matrix. */
+ public DoubleMatrix get(DoubleMatrix indices) {
+ return get(indices.findIndices());
+ }
+
+ /**
+ * Get elements from a row and columns as specified by the non-zero entries of
+ * a matrix.
+ */
+ public DoubleMatrix get(int r, DoubleMatrix indices) {
+ return get(r, indices.findIndices());
+ }
+
+ /**
+ * Get elements from a column and rows as specified by the non-zero entries of
+ * a matrix.
+ */
+ public DoubleMatrix get(DoubleMatrix indices, int c) {
+ return get(indices.findIndices(), c);
+ }
+
+ /**
+ * Get elements from columns and rows as specified by the non-zero entries of
+ * the passed matrices.
+ */
+ public DoubleMatrix get(DoubleMatrix rindices, DoubleMatrix cindices) {
+ return get(rindices.findIndices(), cindices.findIndices());
+ }
+
+ /** Return all elements with linear index a, a + 1, ..., b - 1.*/
+ public DoubleMatrix getRange(int a, int b) {
+ DoubleMatrix result = new DoubleMatrix(b - a);
+
+ for (int k = 0; k < b - a; k++) {
+ result.put(k, get(a + k));
+ }
+
+ return result;
+ }
+
+ /** Get elements from a row and columns <tt>a</tt> to <tt>b</tt>. */
+ public DoubleMatrix getColumnRange(int r, int a, int b) {
+ DoubleMatrix result = new DoubleMatrix(1, b - a);
+
+ for (int k = 0; k < b - a; k++) {
+ result.put(k, get(r, a + k));
+ }
+
+ return result;
+ }
+
+ /** Get elements from a column and rows <tt>a/tt> to <tt>b</tt>. */
+ public DoubleMatrix getRowRange(int a, int b, int c) {
+ DoubleMatrix result = new DoubleMatrix(b - a);
+
+ for (int k = 0; k < b - a; k++) {
+ result.put(k, get(a + k, c));
+ }
+
+ return result;
+ }
+
+ /**
+ * Get elements from rows <tt>ra</tt> to <tt>rb</tt> and
+ * columns <tt>ca</tt> to <tt>cb</tt>.
+ */
+ public DoubleMatrix getRange(int ra, int rb, int ca, int cb) {
+ DoubleMatrix result = new DoubleMatrix(rb - ra, cb - ca);
+
+ for (int i = 0; i < rb - ra; i++) {
+ for (int j = 0; j < cb - ca; j++) {
+ result.put(i, j, get(ra + i, ca + j));
+ }
+ }
+
+ return result;
+ }
+
+ /** Get whole rows from the passed indices. */
+ public DoubleMatrix getRows(int[] rindices) {
+ DoubleMatrix result = new DoubleMatrix(rindices.length, columns);
+ for (int i = 0; i < rindices.length; i++) {
+ JavaBlas.rcopy(columns, data, index(rindices[i], 0), rows, result.data, result.index(i, 0), result.rows);
+ }
+ return result;
+ }
+
+ /** Get whole rows as specified by the non-zero entries of a matrix. */
+ public DoubleMatrix getRows(DoubleMatrix rindices) {
+ return getRows(rindices.findIndices());
+ }
+
+ /** Get whole columns from the passed indices. */
+ public DoubleMatrix getColumns(int[] cindices) {
+ DoubleMatrix result = new DoubleMatrix(rows, cindices.length);
+ for (int i = 0; i < cindices.length; i++) {
+ JavaBlas.rcopy(rows, data, index(0, cindices[i]), 1, result.data, result.index(0, i), 1);
+ }
+ return result;
+ }
+
+ /** Get whole columns as specified by the non-zero entries of a matrix. */
+ public DoubleMatrix getColumns(DoubleMatrix cindices) {
+ return getColumns(cindices.findIndices());
+ }
+
+ /**
+ * Assert that the matrix has a certain length.
+ * @throws SizeException
+ */
+ public void checkLength(int l) {
+ if (length != l) {
+ throw new SizeException("Matrix does not have the necessary length (" + length + " != " + l + ").");
+ }
+ }
+
+ /**
+ * Asserts that the matrix has a certain number of rows.
+ * @throws SizeException
+ */
+ public void checkRows(int r) {
+ if (rows != r) {
+ throw new SizeException("Matrix does not have the necessary number of rows (" + rows + " != " + r + ").");
+ }
+ }
+
+ /**
+ * Asserts that the amtrix has a certain number of columns.
+ * @throws SizeException
+ */
+ public void checkColumns(int c) {
+ if (columns != c) {
+ throw new SizeException("Matrix does not have the necessary number of columns (" + columns + " != " + c + ").");
+ }
+ }
+
+ /** Set elements in linear ordering in the specified indices. */
+ public DoubleMatrix put(int[] indices, DoubleMatrix x) {
+ if (x.isScalar()) {
+ return put(indices, x.scalar());
+ }
+ x.checkLength(indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ put(indices[i], x.get(i));
+ }
+
+ return this;
+ }
+
+ /** Set multiple elements in a row. */
+ public DoubleMatrix put(int r, int[] indices, DoubleMatrix x) {
+ if (x.isScalar()) {
+ return put(r, indices, x.scalar());
+ }
+ x.checkColumns(indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ put(r, indices[i], x.get(i));
+ }
+
+ return this;
+ }
+
+ /** Set multiple elements in a row. */
+ public DoubleMatrix put(int[] indices, int c, DoubleMatrix x) {
+ if (x.isScalar()) {
+ return put(indices, c, x.scalar());
+ }
+ x.checkRows(indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ put(indices[i], c, x.get(i));
+ }
+
+ return this;
+ }
+
+ /** Put a sub-matrix as specified by the indices. */
+ public DoubleMatrix put(int[] rindices, int[] cindices, DoubleMatrix x) {
+ if (x.isScalar()) {
+ return put(rindices, cindices, x.scalar());
+ }
+ x.checkRows(rindices.length);
+ x.checkColumns(cindices.length);
+
+ for (int i = 0; i < rindices.length; i++) {
+ for (int j = 0; j < cindices.length; j++) {
+ put(rindices[i], cindices[j], x.get(i, j));
+ }
+ }
+
+ return this;
+ }
+
+ /** Put a matrix into specified indices. */
+ public DoubleMatrix put(Range rs, Range cs, DoubleMatrix x) {
+ rs.init(0, rows - 1);
+ cs.init(0, columns - 1);
+
+ x.checkRows(rs.length());
+ x.checkColumns(cs.length());
+
+ for (; rs.hasMore(); rs.next()) {
+ for (; cs.hasMore(); cs.next()) {
+ put(rs.value(), cs.value(), x.get(rs.index(), cs.index()));
+ }
+ }
+
+ return this;
+ }
+
+ /** Put a single value into the specified indices (linear adressing). */
+ public DoubleMatrix put(int[] indices, double v) {
+ for (int i = 0; i < indices.length; i++) {
+ put(indices[i], v);
+ }
+
+ return this;
+ }
+
+ /** Put a single value into a row and the specified columns. */
+ public DoubleMatrix put(int r, int[] indices, double v) {
+ for (int i = 0; i < indices.length; i++) {
+ put(r, indices[i], v);
+ }
+
+ return this;
+ }
+
+ /** Put a single value into the specified rows of a column. */
+ public DoubleMatrix put(int[] indices, int c, double v) {
+ for (int i = 0; i < indices.length; i++) {
+ put(indices[i], c, v);
+ }
+
+ return this;
+ }
+
+ /** Put a single value into the specified rows and columns. */
+ public DoubleMatrix put(int[] rindices, int[] cindices, double v) {
+ for (int i = 0; i < rindices.length; i++) {
+ for (int j = 0; j < cindices.length; j++) {
+ put(rindices[i], cindices[j], v);
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Put a sub-matrix into the indices specified by the non-zero entries
+ * of <tt>indices</tt> (linear adressing).
+ */
+ public DoubleMatrix put(DoubleMatrix indices, DoubleMatrix v) {
+ return put(indices.findIndices(), v);
+ }
+
+ /** Put a sub-vector into the specified columns (non-zero entries of <tt>indices</tt>) of a row. */
+ public DoubleMatrix put(int r, DoubleMatrix indices, DoubleMatrix v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ /** Put a sub-vector into the specified rows (non-zero entries of <tt>indices</tt>) of a column. */
+ public DoubleMatrix put(DoubleMatrix indices, int c, DoubleMatrix v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ /**
+ * Put a sub-matrix into the specified rows and columns (non-zero entries of
+ * <tt>rindices</tt> and <tt>cindices</tt>.
+ */
+ public DoubleMatrix put(DoubleMatrix rindices, DoubleMatrix cindices, DoubleMatrix v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ /**
+ * Put a single value into the elements specified by the non-zero
+ * entries of <tt>indices</tt> (linear adressing).
+ */
+ public DoubleMatrix put(DoubleMatrix indices, double v) {
+ return put(indices.findIndices(), v);
+ }
+
+ /**
+ * Put a single value into the specified columns (non-zero entries of
+ * <tt>indices</tt>) of a row.
+ */
+ public DoubleMatrix put(int r, DoubleMatrix indices, double v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ /**
+ * Put a single value into the specified rows (non-zero entries of
+ * <tt>indices</tt>) of a column.
+ */
+ public DoubleMatrix put(DoubleMatrix indices, int c, double v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ /**
+ * Put a single value in the specified rows and columns (non-zero entries
+ * of <tt>rindices</tt> and <tt>cindices</tt>.
+ */
+ public DoubleMatrix put(DoubleMatrix rindices, DoubleMatrix cindices, double v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ /** Find the linear indices of all non-zero elements. */
+ public int[] findIndices() {
+ int len = 0;
+ for (int i = 0; i < length; i++) {
+ if (get(i) != 0.0) {
+ len++;
+ }
+ }
+
+ int[] indices = new int[len];
+ int c = 0;
+
+ for (int i = 0; i < length; i++) {
+ if (get(i) != 0.0) {
+ indices[c++] = i;
+ }
+ }
+
+ return indices;
+ }
+
+ /**************************************************************************
+ * Basic operations (copying, resizing, element access)
+ */
+ /** Return transposed copy of this matrix. */
+ public DoubleMatrix transpose() {
+ DoubleMatrix result = new DoubleMatrix(columns, rows);
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < columns; j++) {
+ result.put(j, i, get(i, j));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Compare two matrices. Returns true if and only if other is also a
+ * DoubleMatrix which has the same size and the maximal absolute
+ * difference in matrix elements is smaller thatn 1e-6.
+ */
+ public boolean equals(Object o) {
+ if (!(o instanceof DoubleMatrix)) {
+ return false;
+ }
+
+ DoubleMatrix other = (DoubleMatrix) o;
+
+ if (!sameSize(other)) {
+ return false;
+ }
+
+ DoubleMatrix diff = MatrixFunctions.absi(sub(other));
+
+ return diff.max() / (rows * columns) < 1e-6;
+ }
+
+ /** Resize the matrix. All elements will be set to zero. */
+ public void resize(int newRows, int newColumns) {
+ rows = newRows;
+ columns = newColumns;
+ length = newRows * newColumns;
+ data = new double[rows * columns];
+ }
+
+ /** Reshape the matrix. Number of elements must not change. */
+ public DoubleMatrix reshape(int newRows, int newColumns) {
+ if (length != newRows * newColumns) {
+ throw new IllegalArgumentException(
+ "Number of elements must not change.");
+ }
+
+ rows = newRows;
+ columns = newColumns;
+
+ return this;
+ }
+
+ /** Generate a new matrix which has the given number of replications of this. */
+ public DoubleMatrix repmat(int rowMult, int columnMult) {
+ DoubleMatrix result = new DoubleMatrix(rows * rowMult, columns * columnMult);
+
+ for (int c = 0; c < columnMult; c++)
+ for (int r = 0; r < rowMult; r++)
+ for (int i = 0; i < rows; i++)
+ for (int j = 0; j < columns; j++)
+ result.put(r * rows + i, c * columns + j, get(i, j));
+ return result;
+ }
+
+ /** Checks whether two matrices have the same size. */
+ public boolean sameSize(DoubleMatrix a) {
+ return rows == a.rows && columns == a.columns;
+ }
+
+ /** Throws SizeException unless two matrices have the same size. */
+ public void assertSameSize(DoubleMatrix a) {
+ if (!sameSize(a)) {
+ throw new SizeException("Matrices must have the same size.");
+ }
+ }
+
+ /** Checks whether two matrices can be multiplied (that is, number of columns of
+ * this must equal number of rows of a. */
+ public boolean multipliesWith(DoubleMatrix a) {
+ return columns == a.rows;
+ }
+
+ /** Throws SizeException unless matrices can be multiplied with one another. */
+ public void assertMultipliesWith(DoubleMatrix a) {
+ if (!multipliesWith(a)) {
+ throw new SizeException("Number of columns of left matrix must be equal to number of rows of right matrix.");
+ }
+ }
+
+ /** Checks whether two matrices have the same length. */
+ public boolean sameLength(DoubleMatrix a) {
+ return length == a.length;
+ }
+
+ /** Throws SizeException unless matrices have the same length. */
+ public void assertSameLength(DoubleMatrix a) {
+ if (!sameLength(a)) {
+ throw new SizeException("Matrices must have same length (is: " + length + " and " + a.length + ")");
+ }
+ }
+
+ /** Copy DoubleMatrix a to this. this a is resized if necessary. */
+ public DoubleMatrix copy(DoubleMatrix a) {
+ if (!sameSize(a)) {
+ resize(a.rows, a.columns);
+ }
+
+ System.arraycopy(data, 0, a.data, 0, length);
+ return a;
+ }
+
+ /**
+ * Returns a duplicate of this matrix. Geometry is the same (including offsets, transpose, etc.),
+ * but the buffer is not shared.
+ */
+ public DoubleMatrix dup() {
+ DoubleMatrix out = new DoubleMatrix(rows, columns);
+
+ JavaBlas.rcopy(length, data, 0, 1, out.data, 0, 1);
+
+ return out;
+ }
+
+ /** Swap two columns of a matrix. */
+ public DoubleMatrix swapColumns(int i, int j) {
+ Blas.dswap(rows, data, index(0, i), 1, data, index(0, j), 1);
+ return this;
+ }
+
+ /** Swap two rows of a matrix. */
+ public DoubleMatrix swapRows(int i, int j) {
+ Blas.dswap(columns, data, index(i, 0), rows, data, index(j, 0), rows);
+ return this;
+ }
+
+ /** Set matrix element */
+ public DoubleMatrix put(int rowIndex, int columnIndex, double value) {
+ data[index(rowIndex, columnIndex)] = value;
+ return this;
+ }
+
+ /** Retrieve matrix element */
+ public double get(int rowIndex, int columnIndex) {
+ return data[index(rowIndex, columnIndex)];
+ }
+
+ /** Get index of an element */
+ public int index(int rowIndex, int columnIndex) {
+ return rowIndex + rows * columnIndex;
+ }
+
+ /** Compute the row index of a linear index. */
+ public int indexRows(int i) {
+ return i / rows;
+ }
+
+ /** Compute the column index of a linear index. */
+ public int indexColumns(int i) {
+ return i - indexRows(i) * rows;
+ }
+
+ /** Get a matrix element (linear indexing). */
+ public double get(int i) {
+ return data[i];
+ }
+
+ /** Set a matrix element (linear indexing). */
+ public DoubleMatrix put(int i, double v) {
+ data[i] = v;
+ return this;
+ }
+
+ /** Set all elements to a value. */
+ public DoubleMatrix fill(double value) {
+ for (int i = 0; i < length; i++) {
+ put(i, value);
+ }
+ return this;
+ }
+
+ /** Get number of rows. */
+ public int getRows() {
+ return rows;
+ }
+
+ /** Get number of columns. */
+ public int getColumns() {
+ return columns;
+ }
+
+ /** Get total number of elements. */
+ public int getLength() {
+ return length;
+ }
+
+ /** Checks whether the matrix is empty. */
+ public boolean isEmpty() {
+ return columns == 0 || rows == 0;
+ }
+
+ /** Checks whether the matrix is square. */
+ public boolean isSquare() {
+ return columns == rows;
+ }
+
+ /** Throw SizeException unless matrix is square. */
+ public void assertSquare() {
+ if (!isSquare()) {
+ throw new SizeException("Matrix must be square!");
+ }
+ }
+
+ /** Checks whether the matrix is a vector. */
+ public boolean isVector() {
+ return columns == 1 || rows == 1;
+ }
+
+ /** Checks whether the matrix is a row vector. */
+ public boolean isRowVector() {
+ return rows == 1;
+ }
+
+ /** Checks whether the matrix is a column vector. */
+ public boolean isColumnVector() {
+ return columns == 1;
+ }
+
+ /** Returns the diagonal of the matrix. */
+ public DoubleMatrix diag() {
+ assertSquare();
+ DoubleMatrix d = new DoubleMatrix(rows);
+ JavaBlas.rcopy(rows, data, 0, rows + 1, d.data, 0, 1);
+ return d;
+ }
+
+ /** Pretty-print this matrix to <tt>System.out</tt>. */
+ public void print() {
+ System.out.println(toString());
+ }
+
+ /** Generate string representation of the matrix. */
+ @Override
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+
+ s.append("[");
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < columns; j++) {
+ s.append(get(i, j));
+ if (j < columns - 1) {
+ s.append(", ");
+ }
+ }
+ if (i < rows - 1) {
+ s.append("; ");
+ }
+ }
+
+ s.append("]");
+
+ return s.toString();
+ }
+
+ /**
+ * Generate string representation of the matrix, with specified
+ * format for the entries. For example, <code>x.toString("%.1f")</code>
+ * generates a string representations having only one position after the
+ * decimal point.
+ */
+ public String toString(String fmt) {
+ StringWriter s = new StringWriter();
+ PrintWriter p = new PrintWriter(s);
+
+ p.print("[");
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ p.printf(fmt, get(r, c));
+ if (c < columns - 1) {
+ p.print(", ");
+ }
+ }
+ if (r < rows - 1) {
+ p.print("; ");
+ }
+ }
+
+ p.print("]");
+
+ return s.toString();
+ }
+
+ /** Converts the matrix to a one-dimensional array of doubles. */
+ public double[] toArray() {
+ double[] array = new double[length];
+
+ System.arraycopy(data, 0, array, 0, length);
+
+ return array;
+ }
+
+ /** Converts the matrix to a two-dimensional array of doubles. */
+ public double[][] toArray2() {
+ double[][] array = new double[rows][columns];
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ array[r][c] = get(r, c);
+ }
+ }
+
+ return array;
+ }
+
+ /** Converts the matrix to a one-dimensional array of integers. */
+ public int[] toIntArray() {
+ int[] array = new int[length];
+
+ for (int i = 0; i < length; i++) {
+ array[i] = (int) Math.rint(get(i));
+ }
+
+ return array;
+ }
+
+ /** Convert the matrix to a two-dimensional array of integers. */
+ public int[][] toIntArray2() {
+ int[][] array = new int[rows][columns];
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ array[r][c] = (int) Math.rint(get(r, c));
+ }
+ }
+
+ return array;
+ }
+
+ /** Convert the matrix to a one-dimensional array of boolean values. */
+ public boolean[] toBooleanArray() {
+ boolean[] array = new boolean[length];
+
+ for (int i = 0; i < length; i++) {
+ array[i] = get(i) != 0.0 ? true : false;
+ }
+
+ return array;
+ }
+
+ /** Convert the matrix to a two-dimensional array of boolean values. */
+ public boolean[][] toBooleanArray2() {
+ boolean[][] array = new boolean[rows][columns];
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ array[r][c] = get(r, c) != 0.0 ? true : false;
+ }
+ }
+
+ return array;
+ }
+
+ /** Convert matrix to FloatMatrix. */
+ public FloatMatrix toFloatMatrix() {
+ FloatMatrix result = new FloatMatrix(rows, columns);
+
+ for (int c = 0; c < columns; c++) {
+ for (int r = 0; r < rows; r++) {
+ result.put(r, c, (float) get(r, c));
+ }
+ }
+
+ return result;
+ }
+
+ /**************************************************************************
+ * Arithmetic Operations
+ */
+ /**
+ * Ensures that the result vector has the same length as this. If not,
+ * resizing result is tried, which fails if result == this or result == other.
+ */
+ private void ensureResultLength(DoubleMatrix other, DoubleMatrix result) {
+ if (!sameLength(result)) {
+ if (result == this || result == other) {
+ throw new SizeException("Cannot resize result matrix because it is used in-place.");
+ }
+ result.resize(rows, columns);
+ }
+ }
+
+ /** Add two matrices (in-place). */
+ public DoubleMatrix addi(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar()) {
+ return addi(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.addi(scalar(), result);
+ }
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ if (result == this) {
+ SimpleBlas.axpy(1.0, other, result);
+ } else if (result == other) {
+ SimpleBlas.axpy(1.0, this, result);
+ } else {
+ /*SimpleBlas.copy(this, result);
+ SimpleBlas.axpy(1.0, other, result);*/
+ JavaBlas.rzgxpy(length, result.data, data, other.data);
+ }
+
+ return result;
+ }
+
+ /** Add a scalar to a matrix (in-place). */
+ public DoubleMatrix addi(double v, DoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) + v);
+ }
+ return result;
+ }
+
+ /** Subtract two matrices (in-place). */
+ public DoubleMatrix subi(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar()) {
+ return subi(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.rsubi(scalar(), result);
+ }
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ if (result == this) {
+ SimpleBlas.axpy(-1.0, other, result);
+ } else if (result == other) {
+ SimpleBlas.scal(-1.0, result);
+ SimpleBlas.axpy(1.0, this, result);
+ } else {
+ SimpleBlas.copy(this, result);
+ SimpleBlas.axpy(-1.0, other, result);
+ }
+ return result;
+ }
+
+ /** Subtract a scalar from a matrix (in-place). */
+ public DoubleMatrix subi(double v, DoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) - v);
+ }
+ return result;
+ }
+
+ /**
+ * Subtract two matrices, but subtract first from second matrix, that is,
+ * compute <em>result = other - this</em> (in-place).
+ * */
+ public DoubleMatrix rsubi(DoubleMatrix other, DoubleMatrix result) {
+ return other.subi(this, result);
+ }
+
+ /** Subtract a matrix from a scalar (in-place). */
+ public DoubleMatrix rsubi(double a, DoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, a - get(i));
+ }
+ return result;
+ }
+
+ /** Elementwise multiplication (in-place). */
+ public DoubleMatrix muli(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar()) {
+ return muli(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.muli(scalar(), result);
+ }
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) * other.get(i));
+ }
+ return result;
+ }
+
+ /** Elementwise multiplication with a scalar (in-place). */
+ public DoubleMatrix muli(double v, DoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) * v);
+ }
+ return result;
+ }
+
+ /** Matrix-matrix multiplication (in-place). */
+ public DoubleMatrix mmuli(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar()) {
+ return muli(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.muli(scalar(), result);
+ }
+
+ /* check sizes and resize if necessary */
+ assertMultipliesWith(other);
+ if (result.rows != rows || result.columns != other.columns) {
+ if (result != this && result != other) {
+ result.resize(rows, other.columns);
+ } else {
+ throw new SizeException("Cannot resize result matrix because it is used in-place.");
+ }
+ }
+
+ if (result == this || result == other) {
+ /* actually, blas cannot do multiplications in-place. Therefore, we will fake by
+ * allocating a temporary object on the side and copy the result later.
+ */
+ DoubleMatrix temp = new DoubleMatrix(result.rows, result.columns);
+ if (other.columns == 1) {
+ SimpleBlas.gemv(1.0, this, other, 0.0, temp);
+ } else {
+ SimpleBlas.gemm(1.0, this, other, 0.0, temp);
+ }
+ SimpleBlas.copy(temp, result);
+ } else {
+ if (other.columns == 1) {
+ SimpleBlas.gemv(1.0, this, other, 0.0, result);
+ } else {
+ SimpleBlas.gemm(1.0, this, other, 0.0, result);
+ }
+ }
+ return result;
+ }
+
+ /** Matrix-matrix multiplication with a scalar (for symmetry, does the
+ * same as <code>muli(scalar)</code> (in-place).
+ */
+ public DoubleMatrix mmuli(double v, DoubleMatrix result) {
+ return muli(v, result);
+ }
+
+ /** Elementwise division (in-place). */
+ public DoubleMatrix divi(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar()) {
+ return divi(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.rdivi(scalar(), result);
+ }
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) / other.get(i));
+ }
+ return result;
+ }
+
+ /** Elementwise division with a scalar (in-place). */
+ public DoubleMatrix divi(double a, DoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) / a);
+ }
+ return result;
+ }
+
+ /**
+ * Elementwise division, with operands switched. Computes
+ * <code>result = other / this</code> (in-place). */
+ public DoubleMatrix rdivi(DoubleMatrix other, DoubleMatrix result) {
+ return other.divi(this, result);
+ }
+
+ /** (Elementwise) division with a scalar, with operands switched. Computes
+ * <code>result = a / this</code> (in-place). */
+ public DoubleMatrix rdivi(double a, DoubleMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, a / get(i));
+ }
+ return result;
+ }
+
+ /** Negate each element (in-place). */
+ public DoubleMatrix negi() {
+ for (int i = 0; i < length; i++) {
+ put(i, -get(i));
+ }
+ return this;
+ }
+
+ /** Negate each element. */
+ public DoubleMatrix neg() {
+ return dup().negi();
+ }
+
+ /** Maps zero to 1.0 and all non-zero values to 0.0 (in-place). */
+ public DoubleMatrix noti() {
+ for (int i = 0; i < length; i++) {
+ put(i, get(i) == 0.0 ? 1.0 : 0.0);
+ }
+ return this;
+ }
+
+ /** Maps zero to 1.0 and all non-zero values to 0.0. */
+ public DoubleMatrix not() {
+ return dup().noti();
+ }
+
+ /** Maps zero to 0.0 and all non-zero values to 1.0 (in-place). */
+ public DoubleMatrix truthi() {
+ for (int i = 0; i < length; i++) {
+ put(i, get(i) == 0.0 ? 0.0 : 1.0);
+ }
+ return this;
+ }
+
+ /** Maps zero to 0.0 and all non-zero values to 1.0. */
+ public DoubleMatrix truth() {
+ return dup().truthi();
+ }
+
+ /****************************************************************
+ * Rank one-updates
+ */
+ /** Computes a rank-1-update A = A + alpha * x * y'. */
+ public DoubleMatrix rankOneUpdate(double alpha, DoubleMatrix x, DoubleMatrix y) {
+ if (rows != x.length) {
+ throw new SizeException("Vector x has wrong length (" + x.length + " != " + rows + ").");
+ }
+ if (columns != y.length) {
+ throw new SizeException("Vector y has wrong length (" + x.length + " != " + columns + ").");
+ }
+
+ SimpleBlas.ger(alpha, x, y, this);
+ return this;
+ }
+
+ /** Computes a rank-1-update A = A + alpha * x * x'. */
+ public DoubleMatrix rankOneUpdate(double alpha, DoubleMatrix x) {
+ return rankOneUpdate(alpha, x, x);
+ }
+
+ /** Computes a rank-1-update A = A + x * x'. */
+ public DoubleMatrix rankOneUpdate(DoubleMatrix x) {
+ return rankOneUpdate(1.0, x, x);
+ }
+
+ /** Computes a rank-1-update A = A + x * y'. */
+ public DoubleMatrix rankOneUpdate(DoubleMatrix x, DoubleMatrix y) {
+ return rankOneUpdate(1.0, x, y);
+ }
+
+ /****************************************************************
+ * Logical operations
+ */
+ /** Returns the minimal element of the matrix. */
+ public double min() {
+ if (isEmpty()) {
+ return Double.POSITIVE_INFINITY;
+ }
+ double v = Double.POSITIVE_INFINITY;
+ for (int i = 0; i < length; i++) {
+ if (!Double.isNaN(get(i)) && get(i) < v) {
+ v = get(i);
+ }
+ }
+
+ return v;
+ }
+
+ /**
+ * Returns the linear index of the minimal element. If there are
+ * more than one elements with this value, the first one is returned.
+ */
+ public int argmin() {
+ if (isEmpty()) {
+ return -1;
+ }
+ double v = Double.POSITIVE_INFINITY;
+ int a = -1;
+ for (int i = 0; i < length; i++) {
+ if (!Double.isNaN(get(i)) && get(i) < v) {
+ v = get(i);
+ a = i;
+ }
+ }
+
+ return a;
+ }
+
+ /**
+ * Computes the minimum between two matrices. Returns the smaller of the
+ * corresponding elements in the matrix (in-place).
+ */
+ public DoubleMatrix mini(DoubleMatrix other, DoubleMatrix result) {
+ if (result == this) {
+ for (int i = 0; i < length; i++) {
+ if (get(i) > other.get(i)) {
+ put(i, other.get(i));
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (get(i) > other.get(i)) {
+ result.put(i, other.get(i));
+ } else {
+ result.put(i, get(i));
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Computes the minimum between two matrices. Returns the smaller of the
+ * corresponding elements in the matrix (in-place on this).
+ */
+ public DoubleMatrix mini(DoubleMatrix other) {
+ return mini(other, this);
+ }
+
+ /**
+ * Computes the minimum between two matrices. Returns the smaller of the
+ * corresponding elements in the matrix (in-place on this).
+ */
+ public DoubleMatrix min(DoubleMatrix other) {
+ return mini(other, new DoubleMatrix(rows, columns));
+ }
+
+ public DoubleMatrix mini(double v, DoubleMatrix result) {
+ if (result == this) {
+ for (int i = 0; i < length; i++) {
+ if (get(i) > v) {
+ result.put(i, v);
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (get(i) > v) {
+ result.put(i, v);
+ } else {
+ result.put(i, get(i));
+ }
+ }
+
+ }
+ return this;
+ }
+
+ public DoubleMatrix mini(double v) {
+ return mini(v, this);
+ }
+
+ public DoubleMatrix min(double v) {
+ return mini(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** Returns the maximal element of the matrix. */
+ public double max() {
+ if (isEmpty()) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ double v = Double.NEGATIVE_INFINITY;
+ for (int i = 0; i < length; i++) {
+ if (!Double.isNaN(get(i)) && get(i) > v) {
+ v = get(i);
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Returns the linear index of the maximal element of the matrix. If
+ * there are more than one elements with this value, the first one
+ * is returned.
+ */
+ public int argmax() {
+ if (isEmpty()) {
+ return -1;
+ }
+ double v = Double.NEGATIVE_INFINITY;
+ int a = -1;
+ for (int i = 0; i < length; i++) {
+ if (!Double.isNaN(get(i)) && get(i) > v) {
+ v = get(i);
+ a = i;
+ }
+ }
+
+ return a;
+ }
+
+ /**
+ * Computes the maximum between two matrices. Returns the larger of the
+ * corresponding elements in the matrix (in-place).
+ */
+ public DoubleMatrix maxi(DoubleMatrix other, DoubleMatrix result) {
+ if (result == this) {
+ for (int i = 0; i < length; i++) {
+ if (get(i) < other.get(i)) {
+ put(i, other.get(i));
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (get(i) < other.get(i)) {
+ result.put(i, other.get(i));
+ } else {
+ result.put(i, get(i));
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Computes the maximum between two matrices. Returns the smaller of the
+ * corresponding elements in the matrix (in-place on this).
+ */
+ public DoubleMatrix maxi(DoubleMatrix other) {
+ return maxi(other, this);
+ }
+
+ /**
+ * Computes the maximum between two matrices. Returns the larger of the
+ * corresponding elements in the matrix (in-place on this).
+ */
+ public DoubleMatrix max(DoubleMatrix other) {
+ return maxi(other, new DoubleMatrix(rows, columns));
+ }
+
+ public DoubleMatrix maxi(double v, DoubleMatrix result) {
+ if (result == this) {
+ for (int i = 0; i < length; i++) {
+ if (get(i) < v) {
+ result.put(i, v);
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (get(i) < v) {
+ result.put(i, v);
+ } else {
+ result.put(i, get(i));
+ }
+ }
+
+ }
+ return this;
+ }
+
+ public DoubleMatrix maxi(double v) {
+ return maxi(v, this);
+ }
+
+ public DoubleMatrix max(double v) {
+ return maxi(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** Computes the sum of all elements of the matrix. */
+ public double sum() {
+ double s = 0.0;
+ for (int i = 0; i < length; i++) {
+ s += get(i);
+ }
+ return s;
+ }
+
+ /**
+ * Computes the mean value of all elements in the matrix,
+ * that is, <code>x.sum() / x.length</code>.
+ */
+ public double mean() {
+ return sum() / length;
+ }
+
+ /**
+ * Computes the cumulative sum, that is, the sum of all elements
+ * of the matrix up to a given index in linear addressing (in-place).
+ */
+ public DoubleMatrix cumulativeSumi() {
+ double s = 0.0;
+ for (int i = 0; i < length; i++) {
+ s += get(i);
+ put(i, s);
+ }
+ return this;
+ }
+
+ /**
+ * Computes the cumulative sum, that is, the sum of all elements
+ * of the matrix up to a given index in linear addressing.
+ */
+ public DoubleMatrix cumulativeSum() {
+ return dup().cumulativeSumi();
+ }
+
+ /** The scalar product of this with other. */
+ public double dot(DoubleMatrix other) {
+ return SimpleBlas.dot(this, other);
+ }
+
+ /**
+ * The Euclidean norm of the matrix as vector, also the Frobenius
+ * norm of the matrix.
+ */
+ public double norm2() {
+ return SimpleBlas.nrm2(this);
+ }
+
+ /**
+ * The maximum norm of the matrix (maximal absolute value of the elements).
+ */
+ public double normmax() {
+ int i = SimpleBlas.iamax(this);
+ return Math.abs(get(i));
+ }
+
+ /**
+ * The 1-norm of the matrix as vector (sum of absolute values of elements).
+ */
+ public double norm1() {
+ return SimpleBlas.asum(this);
+ }
+
+ /**
+ * Return a new matrix with all elements sorted.
+ */
+ public DoubleMatrix sort() {
+ double array[] = toArray();
+ java.util.Arrays.sort(array);
+ return new DoubleMatrix(rows, columns, array);
+ }
+
+ /**
+ * Sort elements in-place.
+ */
+ public DoubleMatrix sorti() {
+ Arrays.sort(data);
+ return this;
+ }
+
+ /**
+ * Get the sorting permutation.
+ *
+ * @return an int[] array such that which indexes the elements in sorted
+ * order.
+ */
+ public int[] sortingPermutation() {
+ Integer[] indices = new Integer[length];
+
+ for (int i = 0; i < length; i++) {
+ indices[i] = i;
+ }
+
+ final double[] array = data;
+
+ Arrays.sort(indices, new Comparator() {
+
+ public int compare(Object o1, Object o2) {
+ int i = (Integer) o1;
+ int j = (Integer) o2;
+ if (array[i] < array[j]) {
+ return -1;
+ } else if (array[i] == array[j]) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ });
+
+ int[] result = new int[length];
+
+ for (int i = 0; i < length; i++) {
+ result[i] = indices[i];
+ }
+
+ return result;
+ }
+
+ /**
+ * Sort columns (in-place).
+ */
+ public DoubleMatrix sortColumnsi() {
+ for (int i = 0; i < length; i += rows) {
+ Arrays.sort(data, i, i + rows);
+ }
+ return this;
+ }
+
+ /** Sort columns. */
+ public DoubleMatrix sortColumns() {
+ return dup().sortColumnsi();
+ }
+
+ /** Return matrix of indices which sort all columns. */
+ public int[][] columnSortingPermutations() {
+ int[][] result = new int[columns][];
+
+ DoubleMatrix temp = new DoubleMatrix(rows);
+ for (int c = 0; c < columns; c++) {
+ result[c] = getColumn(c, temp).sortingPermutation();
+ }
+
+ return result;
+ }
+
+ /** Sort rows (in-place). */
+ public DoubleMatrix sortRowsi() {
+ // actually, this is much harder because the data is not consecutive
+ // in memory...
+ DoubleMatrix temp = new DoubleMatrix(columns);
+ for (int r = 0; r < rows; r++) {
+ putRow(r, getRow(r, temp).sorti());
+ }
+ return this;
+ }
+
+ /** Sort rows. */
+ public DoubleMatrix sortRows() {
+ return dup().sortRowsi();
+ }
+
+ /** Return matrix of indices which sort all columns. */
+ public int[][] rowSortingPermutations() {
+ int[][] result = new int[rows][];
+
+ DoubleMatrix temp = new DoubleMatrix(columns);
+ for (int r = 0; r < rows; r++) {
+ result[r] = getRow(r, temp).sortingPermutation();
+ }
+
+ return result;
+ }
+
+ /** Return a vector containing the sums of the columns (having number of columns many entries) */
+ public DoubleMatrix columnSums() {
+ if (rows == 1) {
+ return dup();
+ } else {
+ DoubleMatrix v = new DoubleMatrix(1, columns);
+
+ for (int c = 0; c < columns; c++) {
+ for (int r = 0; r < rows; r++) {
+ v.put(c, v.get(c) + get(r, c));
+ }
+ }
+
+ return v;
+ }
+ }
+
+ /** Return a vector containing the means of all columns. */
+ public DoubleMatrix columnMeans() {
+ return columnSums().divi(rows);
+ }
+
+ /** Return a vector containing the sum of the rows. */
+ public DoubleMatrix rowSums() {
+ if (columns == 1) {
+ return dup();
+ } else {
+ DoubleMatrix v = new DoubleMatrix(rows);
+
+ for (int c = 0; c < columns; c++) {
+ for (int r = 0; r < rows; r++) {
+ v.put(r, v.get(r) + get(r, c));
+ }
+ }
+
+ return v;
+ }
+ }
+
+ /** Return a vector containing the means of the rows. */
+ public DoubleMatrix rowMeans() {
+ return rowSums().divi(columns);
+ }
+
+ /** Get a copy of a column. */
+ public DoubleMatrix getColumn(int c) {
+ return getColumn(c, new DoubleMatrix(rows, 1));
+ }
+
+ /** Copy a column to the given vector. */
+ public DoubleMatrix getColumn(int c, DoubleMatrix result) {
+ result.checkLength(rows);
+ JavaBlas.rcopy(rows, data, index(0, c), 1, result.data, 0, 1);
+ return result;
+ }
+
+ /** Copy a column back into the matrix. */
+ public void putColumn(int c, DoubleMatrix v) {
+ JavaBlas.rcopy(rows, v.data, 0, 1, data, index(0, c), 1);
+ }
+
+ /** Get a copy of a row. */
+ public DoubleMatrix getRow(int r) {
+ return getRow(r, new DoubleMatrix(1, columns));
+ }
+
+ /** Copy a row to a given vector. */
+ public DoubleMatrix getRow(int r, DoubleMatrix result) {
+ result.checkLength(columns);
+ JavaBlas.rcopy(columns, data, index(r, 0), rows, result.data, 0, 1);
+ return result;
+ }
+
+ /** Copy a row back into the matrix. */
+ public void putRow(int r, DoubleMatrix v) {
+ JavaBlas.rcopy(columns, v.data, 0, 1, data, index(r, 0), rows);
+ }
+
+ /** Return column-wise minimums. */
+ public DoubleMatrix columnMins() {
+ DoubleMatrix mins = new DoubleMatrix(1, columns);
+ for (int c = 0; c < columns; c++) {
+ mins.put(c, getColumn(c).min());
+ }
+ return mins;
+ }
+
+ /** Return index of minimal element per column. */
+ public int[] columnArgmins() {
+ int[] argmins = new int[columns];
+ for (int c = 0; c < columns; c++) {
+ argmins[c] = getColumn(c).argmin();
+ }
+ return argmins;
+ }
+
+ /** Return column-wise maximums. */
+ public DoubleMatrix columnMaxs() {
+ DoubleMatrix maxs = new DoubleMatrix(1, columns);
+ for (int c = 0; c < columns; c++) {
+ maxs.put(c, getColumn(c).max());
+ }
+ return maxs;
+ }
+
+ /** Return index of minimal element per column. */
+ public int[] columnArgmaxs() {
+ int[] argmaxs = new int[columns];
+ for (int c = 0; c < columns; c++) {
+ argmaxs[c] = getColumn(c).argmax();
+ }
+ return argmaxs;
+ }
+
+ /** Return row-wise minimums. */
+ public DoubleMatrix rowMins() {
+ DoubleMatrix mins = new DoubleMatrix(rows);
+ for (int c = 0; c < rows; c++) {
+ mins.put(c, getRow(c).min());
+ }
+ return mins;
+ }
+
+ /** Return index of minimal element per row. */
+ public int[] rowArgmins() {
+ int[] argmins = new int[rows];
+ for (int c = 0; c < rows; c++) {
+ argmins[c] = getRow(c).argmin();
+ }
+ return argmins;
+ }
+
+ /** Return row-wise maximums. */
+ public DoubleMatrix rowMaxs() {
+ DoubleMatrix maxs = new DoubleMatrix(rows);
+ for (int c = 0; c < rows; c++) {
+ maxs.put(c, getRow(c).max());
+ }
+ return maxs;
+ }
+
+ /** Return index of minimal element per row. */
+ public int[] rowArgmaxs() {
+ int[] argmaxs = new int[rows];
+ for (int c = 0; c < rows; c++) {
+ argmaxs[c] = getRow(c).argmax();
+ }
+ return argmaxs;
+ }
+
+ /**************************************************************************
+ * Elementwise Functions
+ */
+ /** Add a row vector to all rows of the matrix (in place). */
+ public DoubleMatrix addiRowVector(DoubleMatrix x) {
+ x.checkLength(columns);
+ for (int r = 0; r < rows; r++) {
+ JavaBlas.raxpy(columns, 1.0, x.data, 0, 1, data, index(r, 0), rows);
+ }
+ return this;
+ }
+
+ /** Add a row to all rows of the matrix. */
+ public DoubleMatrix addRowVector(DoubleMatrix x) {
+ return dup().addiRowVector(x);
+ }
+
+ /** Add a vector to all columns of the matrix (in-place). */
+ public DoubleMatrix addiColumnVector(DoubleMatrix x) {
+ x.checkLength(rows);
+ for (int c = 0; c < columns; c++) {
+ JavaBlas.raxpy(rows, 1.0, x.data, 0, 1, data, index(0, c), 1);
+ }
+ return this;
+ }
+
+ /** Add a vector to all columns of the matrix. */
+ public DoubleMatrix addColumnVector(DoubleMatrix x) {
+ return dup().addiColumnVector(x);
+ }
+
+ /** Subtract a row vector from all rows of the matrix (in-place). */
+ public DoubleMatrix subiRowVector(DoubleMatrix x) {
+ // This is a bit crazy, but a row vector must have as length as the columns of the matrix.
+ x.checkLength(columns);
+ for (int r = 0; r < rows; r++) {
+ JavaBlas.raxpy(columns, -1.0, x.data, 0, 1, data, index(r, 0), rows);
+ }
+ return this;
+ }
+
+ /** Subtract a row vector from all rows of the matrix. */
+ public DoubleMatrix subRowVector(DoubleMatrix x) {
+ return dup().subiRowVector(x);
+ }
+
+ /** Subtract a column vector from all columns of the matrix (in-place). */
+ public DoubleMatrix subiColumnVector(DoubleMatrix x) {
+ x.checkLength(rows);
+ for (int c = 0; c < columns; c++) {
+ JavaBlas.raxpy(rows, -1.0, x.data, 0, 1, data, index(0, c), 1);
+ }
+ return this;
+ }
+
+ /** Subtract a vector from all columns of the matrix. */
+ public DoubleMatrix subColumnVector(DoubleMatrix x) {
+ return dup().subiColumnVector(x);
+ }
+
+ /** Multiply a row by a scalar. */
+ public DoubleMatrix mulRow(int r, double scale) {
+ Blas.dscal(columns, scale, data, index(r, 0), rows);
+ return this;
+ }
+
+ /** Multiply a column by a scalar. */
+ public DoubleMatrix mulColumn(int c, double scale) {
+ Blas.dscal(rows, scale, data, index(0, c), 1);
+ return this;
+ }
+
+ /** Multiply all columns with a column vector (in-place). */
+ public DoubleMatrix muliColumnVector(DoubleMatrix x) {
+ x.checkLength(rows);
+ for (int c = 0; c < columns; c++) {
+ for (int r = 0; r < rows; r++)
+ put(r, c, get(r, c) * x.get(r));
+ }
+ return this;
+ }
+
+ /** Multiply all columns with a column vector. */
+ public DoubleMatrix mulColumnVector(DoubleMatrix x) {
+ return dup().muliColumnVector(x);
+ }
+
+ /** Multiply all rows with a row vector (in-place). */
+ public DoubleMatrix muliRowVector(DoubleMatrix x) {
+ x.checkLength(columns);
+ for (int c = 0; c < columns; c++)
+ for (int r = 0; r < rows; r++)
+ put(r, c, get(r, c) * x.get(c));
+ return this;
+ }
+
+ /** Multiply all rows with a row vector. */
+ public DoubleMatrix mulRowVector(DoubleMatrix x) {
+ return dup().muliRowVector(x);
+ }
+
+ /**
+ * Writes out this matrix to the given data stream.
+ * @param dos the data output stream to write to.
+ * @throws IOException
+ */
+ public void out(DataOutputStream dos) throws IOException {
+ dos.writeUTF("double");
+ dos.writeInt(columns);
+ dos.writeInt(rows);
+
+ dos.writeInt(data.length);
+ for (int i = 0; i < data.length; i++) {
+ dos.writeDouble(data[i]);
+ }
+ }
+
+ /**
+ * Reads in a matrix from the given data stream. Note
+ * that the old data of this matrix will be discarded.
+ * @param dis the data input stream to read from.
+ * @throws IOException
+ */
+ public void in(DataInputStream dis) throws IOException {
+ if (!dis.readUTF().equals("double")) {
+ throw new IllegalStateException("The matrix in the specified file is not of the correct type!");
+ }
+
+ this.columns = dis.readInt();
+ this.rows = dis.readInt();
+
+ final int MAX = dis.readInt();
+ data = new double[MAX];
+ for (int i = 0; i < MAX; i++) {
+ data[i] = dis.readDouble();
+ }
+ }
+
+ /**
+ * Saves this matrix to the specified file.
+ * @param filename the file to write the matrix in.
+ * @throws IOException thrown on errors while writing the matrix to the file
+ */
+ public void save(String filename) throws IOException {
+ DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename, false));
+ this.out(dos);
+ }
+
+ /**
+ * Loads a matrix from a file into this matrix. Note that the old data
+ * of this matrix will be discarded.
+ * @param filename the file to read the matrix from
+ * @throws IOException thrown on errors while reading the matrix
+ */
+ public void load(String filename) throws IOException {
+ DataInputStream dis = new DataInputStream(new FileInputStream(filename));
+ this.in(dis);
+ }
+
+ public static DoubleMatrix loadAsciiFile(String filename) throws IOException {
+ BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+
+ // Go through file and count columns and rows. What makes this endeavour a bit difficult is
+ // that files can have leading or trailing spaces leading to spurious fields
+ // after String.split().
+ String line;
+ int rows = 0;
+ int columns = -1;
+ while ((line = is.readLine()) != null) {
+ String[] elements = line.split("\\s+");
+ int numElements = elements.length;
+ if (elements[0].length() == 0) {
+ numElements--;
+ }
+ if (elements[elements.length - 1].length() == 0) {
+ numElements--;
+ }
+
+ if (columns == -1) {
+ columns = numElements;
+ } else {
+ if (columns != numElements) {
+ throw new IOException("Number of elements changes in line " + line + ".");
+ }
+ }
+
+ rows++;
+ }
+ is.close();
+
+ // Go through file a second time process the actual data.
+ is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+ DoubleMatrix result = new DoubleMatrix(rows, columns);
+ int r = 0;
+ while ((line = is.readLine()) != null) {
+ String[] elements = line.split("\\s+");
+ int firstElement = (elements[0].length() == 0) ? 1 : 0;
+ for (int c = 0, cc = firstElement; c < columns; c++, cc++) {
+ result.put(r, c, Double.valueOf(elements[cc]));
+ }
+ r++;
+ }
+ return result;
+ }
+
+ /****************************************************************
+ * Autogenerated code
+ */
+ /***** Code for operators ***************************************/
+
+ /* Overloads for the usual arithmetic operations */
+ /*#
+ def gen_overloads(base, result_rows, result_cols, verb=''); <<-EOS
+ #{doc verb.capitalize + " a matrix (in place)."}
+ public DoubleMatrix #{base}i(DoubleMatrix other) {
+ return #{base}i(other, this);
+ }
+
+ #{doc verb.capitalize + " a matrix (in place)."}
+ public DoubleMatrix #{base}(DoubleMatrix other) {
+ return #{base}i(other, new DoubleMatrix(#{result_rows}, #{result_cols}));
+ }
+
+ #{doc verb.capitalize + " a scalar (in place)."}
+ public DoubleMatrix #{base}i(double v) {
+ return #{base}i(v, this);
+ }
+
+ #{doc verb.capitalize + " a scalar."}
+ public DoubleMatrix #{base}(double v) {
+ return #{base}i(v, new DoubleMatrix(rows, columns));
+ }
+ EOS
+ end
+ #*/
+
+ /* Generating code for logical operators. This not only generates the stubs
+ * but really all of the code.
+ */
+ /*#
+ def gen_compare(name, op, cmp); <<-EOS
+ #{doc 'Test for ' + cmp + ' (in-place).'}
+ public DoubleMatrix #{name}i(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar())
+ return #{name}i(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) #{op} other.get(i) ? 1.0 : 0.0);
+ return result;
+ }
+
+ #{doc 'Test for ' + cmp + ' (in-place).'}
+ public DoubleMatrix #{name}i(DoubleMatrix other) {
+ return #{name}i(other, this);
+ }
+
+ #{doc 'Test for ' + cmp + '.'}
+ public DoubleMatrix #{name}(DoubleMatrix other) {
+ return #{name}i(other, new DoubleMatrix(rows, columns));
+ }
+
+ #{doc 'Test for ' + cmp + ' against a scalar (in-place).'}
+ public DoubleMatrix #{name}i(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) #{op} value ? 1.0 : 0.0);
+ return result;
+ }
+
+ #{doc 'Test for ' + cmp + ' against a scalar (in-place).'}
+ public DoubleMatrix #{name}i(double value) {
+ return #{name}i(value, this);
+ }
+
+ #{doc 'test for ' + cmp + ' against a scalar.'}
+ public DoubleMatrix #{name}(double value) {
+ return #{name}i(value, new DoubleMatrix(rows, columns));
+ }
+ EOS
+ end
+ #*/
+ /*#
+ def gen_logical(name, op, cmp); <<-EOS
+ #{doc 'Compute elementwise ' + cmp + ' (in-place).'}
+ public DoubleMatrix #{name}i(DoubleMatrix other, DoubleMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0) #{op} (other.get(i) != 0.0) ? 1.0 : 0.0);
+ return result;
+ }
+
+ #{doc 'Compute elementwise ' + cmp + ' (in-place).'}
+ public DoubleMatrix #{name}i(DoubleMatrix other) {
+ return #{name}i(other, this);
+ }
+
+ #{doc 'Compute elementwise ' + cmp + '.'}
+ public DoubleMatrix #{name}(DoubleMatrix other) {
+ return #{name}i(other, new DoubleMatrix(rows, columns));
+ }
+
+ #{doc 'Compute elementwise ' + cmp + ' against a scalar (in-place).'}
+ public DoubleMatrix #{name}i(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = (value != 0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0) #{op} val ? 1.0 : 0.0);
+ return result;
+ }
+
+ #{doc 'Compute elementwise ' + cmp + ' against a scalar (in-place).'}
+ public DoubleMatrix #{name}i(double value) {
+ return #{name}i(value, this);
+ }
+
+ #{doc 'Compute elementwise ' + cmp + ' against a scalar.'}
+ public DoubleMatrix #{name}(double value) {
+ return #{name}i(value, new DoubleMatrix(rows, columns));
+ }
+ EOS
+ end
+ #*/
+
+ /*# collect(gen_overloads('add', 'rows', 'columns', 'add'),
+ gen_overloads('sub', 'rows', 'columns', 'subtract'),
+ gen_overloads('rsub', 'rows', 'columns', '(right-)subtract'),
+ gen_overloads('div', 'rows', 'columns', 'elementwise divide by'),
+ gen_overloads('rdiv', 'rows', 'columns', '(right-)elementwise divide by'),
+ gen_overloads('mul', 'rows', 'columns', 'elementwise multiply by'),
+ gen_overloads('mmul', 'rows', 'other.columns', 'matrix-multiply by'),
+ gen_compare('lt', '<', '"less than"'),
+ gen_compare('gt', '>', '"greater than"'),
+ gen_compare('le', '<=', '"less than or equal"'),
+ gen_compare('ge', '>=', '"greater than or equal"'),
+ gen_compare('eq', '==', 'equality'),
+ gen_compare('ne', '!=', 'inequality'),
+ gen_logical('and', '&', 'logical and'),
+ gen_logical('or', '|', 'logical or'),
+ gen_logical('xor', '^', 'logical xor'))
+ #*/
+//RJPP-BEGIN------------------------------------------------------------
+ /** Add a matrix (in place). */
+ public DoubleMatrix addi(DoubleMatrix other) {
+ return addi(other, this);
+ }
+
+ /** Add a matrix (in place). */
+ public DoubleMatrix add(DoubleMatrix other) {
+ return addi(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Add a scalar (in place). */
+ public DoubleMatrix addi(double v) {
+ return addi(v, this);
+ }
+
+ /** Add a scalar. */
+ public DoubleMatrix add(double v) {
+ return addi(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** Subtract a matrix (in place). */
+ public DoubleMatrix subi(DoubleMatrix other) {
+ return subi(other, this);
+ }
+
+ /** Subtract a matrix (in place). */
+ public DoubleMatrix sub(DoubleMatrix other) {
+ return subi(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Subtract a scalar (in place). */
+ public DoubleMatrix subi(double v) {
+ return subi(v, this);
+ }
+
+ /** Subtract a scalar. */
+ public DoubleMatrix sub(double v) {
+ return subi(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** (right-)subtract a matrix (in place). */
+ public DoubleMatrix rsubi(DoubleMatrix other) {
+ return rsubi(other, this);
+ }
+
+ /** (right-)subtract a matrix (in place). */
+ public DoubleMatrix rsub(DoubleMatrix other) {
+ return rsubi(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** (right-)subtract a scalar (in place). */
+ public DoubleMatrix rsubi(double v) {
+ return rsubi(v, this);
+ }
+
+ /** (right-)subtract a scalar. */
+ public DoubleMatrix rsub(double v) {
+ return rsubi(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** Elementwise divide by a matrix (in place). */
+ public DoubleMatrix divi(DoubleMatrix other) {
+ return divi(other, this);
+ }
+
+ /** Elementwise divide by a matrix (in place). */
+ public DoubleMatrix div(DoubleMatrix other) {
+ return divi(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Elementwise divide by a scalar (in place). */
+ public DoubleMatrix divi(double v) {
+ return divi(v, this);
+ }
+
+ /** Elementwise divide by a scalar. */
+ public DoubleMatrix div(double v) {
+ return divi(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** (right-)elementwise divide by a matrix (in place). */
+ public DoubleMatrix rdivi(DoubleMatrix other) {
+ return rdivi(other, this);
+ }
+
+ /** (right-)elementwise divide by a matrix (in place). */
+ public DoubleMatrix rdiv(DoubleMatrix other) {
+ return rdivi(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** (right-)elementwise divide by a scalar (in place). */
+ public DoubleMatrix rdivi(double v) {
+ return rdivi(v, this);
+ }
+
+ /** (right-)elementwise divide by a scalar. */
+ public DoubleMatrix rdiv(double v) {
+ return rdivi(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** Elementwise multiply by a matrix (in place). */
+ public DoubleMatrix muli(DoubleMatrix other) {
+ return muli(other, this);
+ }
+
+ /** Elementwise multiply by a matrix (in place). */
+ public DoubleMatrix mul(DoubleMatrix other) {
+ return muli(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Elementwise multiply by a scalar (in place). */
+ public DoubleMatrix muli(double v) {
+ return muli(v, this);
+ }
+
+ /** Elementwise multiply by a scalar. */
+ public DoubleMatrix mul(double v) {
+ return muli(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** Matrix-multiply by a matrix (in place). */
+ public DoubleMatrix mmuli(DoubleMatrix other) {
+ return mmuli(other, this);
+ }
+
+ /** Matrix-multiply by a matrix (in place). */
+ public DoubleMatrix mmul(DoubleMatrix other) {
+ return mmuli(other, new DoubleMatrix(rows, other.columns));
+ }
+
+ /** Matrix-multiply by a scalar (in place). */
+ public DoubleMatrix mmuli(double v) {
+ return mmuli(v, this);
+ }
+
+ /** Matrix-multiply by a scalar. */
+ public DoubleMatrix mmul(double v) {
+ return mmuli(v, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for "less than" (in-place). */
+ public DoubleMatrix lti(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar())
+ return lti(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) < other.get(i) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for "less than" (in-place). */
+ public DoubleMatrix lti(DoubleMatrix other) {
+ return lti(other, this);
+ }
+
+ /** Test for "less than". */
+ public DoubleMatrix lt(DoubleMatrix other) {
+ return lti(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for "less than" against a scalar (in-place). */
+ public DoubleMatrix lti(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) < value ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for "less than" against a scalar (in-place). */
+ public DoubleMatrix lti(double value) {
+ return lti(value, this);
+ }
+
+ /** test for "less than" against a scalar. */
+ public DoubleMatrix lt(double value) {
+ return lti(value, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for "greater than" (in-place). */
+ public DoubleMatrix gti(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar())
+ return gti(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) > other.get(i) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for "greater than" (in-place). */
+ public DoubleMatrix gti(DoubleMatrix other) {
+ return gti(other, this);
+ }
+
+ /** Test for "greater than". */
+ public DoubleMatrix gt(DoubleMatrix other) {
+ return gti(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for "greater than" against a scalar (in-place). */
+ public DoubleMatrix gti(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) > value ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for "greater than" against a scalar (in-place). */
+ public DoubleMatrix gti(double value) {
+ return gti(value, this);
+ }
+
+ /** test for "greater than" against a scalar. */
+ public DoubleMatrix gt(double value) {
+ return gti(value, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for "less than or equal" (in-place). */
+ public DoubleMatrix lei(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar())
+ return lei(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) <= other.get(i) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for "less than or equal" (in-place). */
+ public DoubleMatrix lei(DoubleMatrix other) {
+ return lei(other, this);
+ }
+
+ /** Test for "less than or equal". */
+ public DoubleMatrix le(DoubleMatrix other) {
+ return lei(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for "less than or equal" against a scalar (in-place). */
+ public DoubleMatrix lei(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) <= value ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for "less than or equal" against a scalar (in-place). */
+ public DoubleMatrix lei(double value) {
+ return lei(value, this);
+ }
+
+ /** test for "less than or equal" against a scalar. */
+ public DoubleMatrix le(double value) {
+ return lei(value, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for "greater than or equal" (in-place). */
+ public DoubleMatrix gei(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar())
+ return gei(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) >= other.get(i) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for "greater than or equal" (in-place). */
+ public DoubleMatrix gei(DoubleMatrix other) {
+ return gei(other, this);
+ }
+
+ /** Test for "greater than or equal". */
+ public DoubleMatrix ge(DoubleMatrix other) {
+ return gei(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for "greater than or equal" against a scalar (in-place). */
+ public DoubleMatrix gei(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) >= value ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for "greater than or equal" against a scalar (in-place). */
+ public DoubleMatrix gei(double value) {
+ return gei(value, this);
+ }
+
+ /** test for "greater than or equal" against a scalar. */
+ public DoubleMatrix ge(double value) {
+ return gei(value, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for equality (in-place). */
+ public DoubleMatrix eqi(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar())
+ return eqi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) == other.get(i) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for equality (in-place). */
+ public DoubleMatrix eqi(DoubleMatrix other) {
+ return eqi(other, this);
+ }
+
+ /** Test for equality. */
+ public DoubleMatrix eq(DoubleMatrix other) {
+ return eqi(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for equality against a scalar (in-place). */
+ public DoubleMatrix eqi(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) == value ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for equality against a scalar (in-place). */
+ public DoubleMatrix eqi(double value) {
+ return eqi(value, this);
+ }
+
+ /** test for equality against a scalar. */
+ public DoubleMatrix eq(double value) {
+ return eqi(value, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for inequality (in-place). */
+ public DoubleMatrix nei(DoubleMatrix other, DoubleMatrix result) {
+ if (other.isScalar())
+ return nei(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) != other.get(i) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for inequality (in-place). */
+ public DoubleMatrix nei(DoubleMatrix other) {
+ return nei(other, this);
+ }
+
+ /** Test for inequality. */
+ public DoubleMatrix ne(DoubleMatrix other) {
+ return nei(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Test for inequality against a scalar (in-place). */
+ public DoubleMatrix nei(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) != value ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Test for inequality against a scalar (in-place). */
+ public DoubleMatrix nei(double value) {
+ return nei(value, this);
+ }
+
+ /** test for inequality against a scalar. */
+ public DoubleMatrix ne(double value) {
+ return nei(value, new DoubleMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical and (in-place). */
+ public DoubleMatrix andi(DoubleMatrix other, DoubleMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0) & (other.get(i) != 0.0) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Compute elementwise logical and (in-place). */
+ public DoubleMatrix andi(DoubleMatrix other) {
+ return andi(other, this);
+ }
+
+ /** Compute elementwise logical and. */
+ public DoubleMatrix and(DoubleMatrix other) {
+ return andi(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical and against a scalar (in-place). */
+ public DoubleMatrix andi(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = (value != 0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0) & val ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Compute elementwise logical and against a scalar (in-place). */
+ public DoubleMatrix andi(double value) {
+ return andi(value, this);
+ }
+
+ /** Compute elementwise logical and against a scalar. */
+ public DoubleMatrix and(double value) {
+ return andi(value, new DoubleMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical or (in-place). */
+ public DoubleMatrix ori(DoubleMatrix other, DoubleMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0) | (other.get(i) != 0.0) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Compute elementwise logical or (in-place). */
+ public DoubleMatrix ori(DoubleMatrix other) {
+ return ori(other, this);
+ }
+
+ /** Compute elementwise logical or. */
+ public DoubleMatrix or(DoubleMatrix other) {
+ return ori(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical or against a scalar (in-place). */
+ public DoubleMatrix ori(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = (value != 0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0) | val ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Compute elementwise logical or against a scalar (in-place). */
+ public DoubleMatrix ori(double value) {
+ return ori(value, this);
+ }
+
+ /** Compute elementwise logical or against a scalar. */
+ public DoubleMatrix or(double value) {
+ return ori(value, new DoubleMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical xor (in-place). */
+ public DoubleMatrix xori(DoubleMatrix other, DoubleMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0) ^ (other.get(i) != 0.0) ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Compute elementwise logical xor (in-place). */
+ public DoubleMatrix xori(DoubleMatrix other) {
+ return xori(other, this);
+ }
+
+ /** Compute elementwise logical xor. */
+ public DoubleMatrix xor(DoubleMatrix other) {
+ return xori(other, new DoubleMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical xor against a scalar (in-place). */
+ public DoubleMatrix xori(double value, DoubleMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = (value != 0.0);
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0) ^ val ? 1.0 : 0.0);
+ return result;
+ }
+
+ /** Compute elementwise logical xor against a scalar (in-place). */
+ public DoubleMatrix xori(double value) {
+ return xori(value, this);
+ }
+
+ /** Compute elementwise logical xor against a scalar. */
+ public DoubleMatrix xor(double value) {
+ return xori(value, new DoubleMatrix(rows, columns));
+ }
+//RJPP-END--------------------------------------------------------------
+}
diff --git a/src/org/jblas/la/Eigen.java b/src/org/jblas/la/Eigen.java
new file mode 100644
index 0000000..fe3b6df
--- /dev/null
+++ b/src/org/jblas/la/Eigen.java
@@ -0,0 +1,188 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+/**
+ * <p>Eigenvalue and Eigenvector related functions.</p>
+ *
+ * <p>Methods exist for working with symmetric matrices or general eigenvalues.
+ * The symmetric versions are usually much faster on symmetric matrices.</p>
+ */
+public class Eigen {
+ private static final DoubleMatrix dummyDouble = new DoubleMatrix(1);
+
+ /** Compute the eigenvalues for a symmetric matrix. */
+ public static DoubleMatrix symmetricEigenvalues(DoubleMatrix A) {
+ A.assertSquare();
+ DoubleMatrix eigenvalues = new DoubleMatrix(A.rows);
+ int isuppz[] = new int[2*A.rows];
+ SimpleBlas.syevr('N', 'A', 'U', A.dup(), 0, 0, 0, 0, 0, eigenvalues, dummyDouble, isuppz);
+ return eigenvalues;
+ }
+
+ /**
+ * Computes the eigenvalues and eigenvectors for a symmetric matrix.
+ *
+ * @return an array of DoubleMatrix objects containing the eigenvectors
+ * stored as the columns of the first matrix, and the eigenvalues as
+ * diagonal elements of the second matrix.
+ */
+ public static DoubleMatrix[] symmetricEigenvectors(DoubleMatrix A) {
+ A.assertSquare();
+ DoubleMatrix eigenvalues = new DoubleMatrix(A.rows);
+ DoubleMatrix eigenvectors = A.dup();
+ int isuppz[] = new int[2*A.rows];
+ SimpleBlas.syevr('V', 'A', 'U', A.dup(), 0, 0, 0, 0, 0, eigenvalues, eigenvectors, isuppz);
+ return new DoubleMatrix[] { eigenvectors, DoubleMatrix.diag(eigenvalues) };
+ }
+
+ /** Computes the eigenvalues of a general matrix. */
+ public static ComplexDoubleMatrix eigenvalues(DoubleMatrix A) {
+ A.assertSquare();
+ DoubleMatrix WR = new DoubleMatrix(A.rows);
+ DoubleMatrix WI = WR.dup();
+ SimpleBlas.geev('N', 'N', A.dup(), WR, WI, dummyDouble, dummyDouble);
+
+ return new ComplexDoubleMatrix(WR, WI);
+ }
+
+ /**
+ * Computes the eigenvalues and eigenvectors of a general matrix.
+ *
+ * @return an array of ComplexDoubleMatrix objects containing the eigenvectors
+ * stored as the columns of the first matrix, and the eigenvalues as the
+ * diagonal elements of the second matrix.
+ */
+ public static ComplexDoubleMatrix[] eigenvectors(DoubleMatrix A) {
+ A.assertSquare();
+ // setting up result arrays
+ DoubleMatrix WR = new DoubleMatrix(A.rows);
+ DoubleMatrix WI = WR.dup();
+ DoubleMatrix VR = new DoubleMatrix(A.rows, A.rows);
+
+ SimpleBlas.geev('N', 'V', A.dup(), WR, WI, dummyDouble, VR);
+
+ // transferring the result
+ ComplexDoubleMatrix E = new ComplexDoubleMatrix(WR, WI);
+ ComplexDoubleMatrix V = new ComplexDoubleMatrix(A.rows, A.rows);
+ System.err.printf("VR = %s\n", VR.toString());
+ for (int i = 0; i < A.rows; i++) {
+ if (E.get(i).isReal()) {
+ V.putColumn(i, new ComplexDoubleMatrix(VR.getColumn(i)));
+ } else {
+ ComplexDoubleMatrix v = new ComplexDoubleMatrix(VR.getColumn(i), VR.getColumn(i+1));
+ V.putColumn(i, v);
+ V.putColumn(i+1, v.conji());
+ i += 1;
+ }
+ }
+ return new ComplexDoubleMatrix[] { V, ComplexDoubleMatrix.diag(E) };
+ }
+//BEGIN
+ // The code below has been automatically generated.
+ // DO NOT EDIT!
+ private static final FloatMatrix dummyFloat = new FloatMatrix(1);
+
+ /** Compute the eigenvalues for a symmetric matrix. */
+ public static FloatMatrix symmetricEigenvalues(FloatMatrix A) {
+ A.assertSquare();
+ FloatMatrix eigenvalues = new FloatMatrix(A.rows);
+ int isuppz[] = new int[2*A.rows];
+ SimpleBlas.syevr('N', 'A', 'U', A.dup(), 0, 0, 0, 0, 0, eigenvalues, dummyFloat, isuppz);
+ return eigenvalues;
+ }
+
+ /**
+ * Computes the eigenvalues and eigenvectors for a symmetric matrix.
+ *
+ * @return an array of FloatMatrix objects containing the eigenvectors
+ * stored as the columns of the first matrix, and the eigenvalues as
+ * diagonal elements of the second matrix.
+ */
+ public static FloatMatrix[] symmetricEigenvectors(FloatMatrix A) {
+ A.assertSquare();
+ FloatMatrix eigenvalues = new FloatMatrix(A.rows);
+ FloatMatrix eigenvectors = A.dup();
+ int isuppz[] = new int[2*A.rows];
+ SimpleBlas.syevr('V', 'A', 'U', A.dup(), 0, 0, 0, 0, 0, eigenvalues, eigenvectors, isuppz);
+ return new FloatMatrix[] { eigenvectors, FloatMatrix.diag(eigenvalues) };
+ }
+
+ /** Computes the eigenvalues of a general matrix. */
+ public static ComplexFloatMatrix eigenvalues(FloatMatrix A) {
+ A.assertSquare();
+ FloatMatrix WR = new FloatMatrix(A.rows);
+ FloatMatrix WI = WR.dup();
+ SimpleBlas.geev('N', 'N', A.dup(), WR, WI, dummyFloat, dummyFloat);
+
+ return new ComplexFloatMatrix(WR, WI);
+ }
+
+ /**
+ * Computes the eigenvalues and eigenvectors of a general matrix.
+ *
+ * @return an array of ComplexFloatMatrix objects containing the eigenvectors
+ * stored as the columns of the first matrix, and the eigenvalues as the
+ * diagonal elements of the second matrix.
+ */
+ public static ComplexFloatMatrix[] eigenvectors(FloatMatrix A) {
+ A.assertSquare();
+ // setting up result arrays
+ FloatMatrix WR = new FloatMatrix(A.rows);
+ FloatMatrix WI = WR.dup();
+ FloatMatrix VR = new FloatMatrix(A.rows, A.rows);
+
+ SimpleBlas.geev('N', 'V', A.dup(), WR, WI, dummyFloat, VR);
+
+ // transferring the result
+ ComplexFloatMatrix E = new ComplexFloatMatrix(WR, WI);
+ ComplexFloatMatrix V = new ComplexFloatMatrix(A.rows, A.rows);
+ System.err.printf("VR = %s\n", VR.toString());
+ for (int i = 0; i < A.rows; i++) {
+ if (E.get(i).isReal()) {
+ V.putColumn(i, new ComplexFloatMatrix(VR.getColumn(i)));
+ } else {
+ ComplexFloatMatrix v = new ComplexFloatMatrix(VR.getColumn(i), VR.getColumn(i+1));
+ V.putColumn(i, v);
+ V.putColumn(i+1, v.conji());
+ i += 1;
+ }
+ }
+ return new ComplexFloatMatrix[] { V, ComplexFloatMatrix.diag(E) };
+ }
+//END
+}
diff --git a/src/org/jblas/la/FloatFunction.java b/src/org/jblas/la/FloatFunction.java
new file mode 100644
index 0000000..150e58c
--- /dev/null
+++ b/src/org/jblas/la/FloatFunction.java
@@ -0,0 +1,45 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+/**
+ * Represents a function on floats.
+ */
+public interface FloatFunction {
+ /** Compute the function. */
+ public float compute(float x);
+}
diff --git a/src/org/jblas/la/FloatMatrix.java b/src/org/jblas/la/FloatMatrix.java
new file mode 100644
index 0000000..2bda548
--- /dev/null
+++ b/src/org/jblas/la/FloatMatrix.java
@@ -0,0 +1,2965 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * Copyright (c) 2008, Johannes Schaback
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.exceptions.SizeException;
+import org.jblas.la.ranges.Range;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * A general matrix class for <tt>float</tt> typed values.
+ *
+ * Don't be intimidated by the large number of methods this function defines. Most
+ * are overloads provided for ease of use. For example, for each arithmetic operation,
+ * up to six overloaded versions exist to handle in-place computations, and
+ * scalar arguments.
+ *
+ * <h3>Construction</h3>
+ *
+ * <p>To construct a two-dimensional matrices, you can use the following constructors
+ * and static methods.</p>
+ *
+ * <table class="my">
+ * <tr><th>Method<th>Description
+ * <tr><td>FloatMatrix(m,n, [value1, value2, value3...])<td>Values are filled in row by row.
+ * <tr><td>FloatMatrix(new float[][] {{value1, value2, ...}, ...}<td>Inner arrays are columns.
+ * <tr><td>FloatMatrix.zeros(m,n) <td>Initial values set to 0.0f.
+ * <tr><td>FloatMatrix.ones(m,n) <td>Initial values set to 1.0f.
+ * <tr><td>FloatMatrix.rand(m,n) <td>Values drawn at random between 0.0f and 1.0f.
+ * <tr><td>FloatMatrix.randn(m,n) <td>Values drawn from normal distribution.
+ * <tr><td>FloatMatrix.eye(n) <td>Unit matrix (values 0.0f except for 1.0f on the diagonal).
+ * <tr><td>FloatMatrix.diag(array) <td>Diagonal matrix with given diagonal elements.
+ * </table>
+ *
+ * <p>Alternatively, you can construct (column) vectors, if you just supply the length
+ * using the following constructors and static methods.</p>
+ *
+ * <table class="my">
+ * <tr><th>Method<th>Description
+ * <tr><td>FloatMatrix(m)<td>Constructs a column vector.
+ * <tr><td>FloatMatrix(new float[] {value1, value2, ...})<td>Constructs a column vector.
+ * <tr><td>FloatMatrix.zeros(m) <td>Initial values set to 1.0f.
+ * <tr><td>FloatMatrix.ones(m) <td>Initial values set to 0.0f.
+ * <tr><td>FloatMatrix.rand(m) <td>Values drawn at random between 0.0f and 1.0f.
+ * <tr><td>FloatMatrix.randn(m) <td>Values drawn from normal distribution.
+ * </table>
+ *
+ * <p>You can also construct new matrices by concatenating matrices either horziontally
+ * or vertically:</p>
+ *
+ * <table class="my">
+ * <tr><th>Method<th>Description
+ * <tr><td>x.concatHorizontally(y)<td>New matrix will be x next to y.
+ * <tr><td>x.concatVertically(y)<td>New matrix will be x atop y.
+ * </table>
+ *
+ * <h3>Element Access, Copying and Duplication</h3>
+ *
+ * <p>To access individual elements, or whole rows and columns, use the following
+ * methods:<p>
+ *
+ * <table class="my">
+ * <tr><th>x.Method<th>Description
+ * <tr><td>x.get(i,j)<td>Get element in row i and column j.
+ * <tr><td>x.put(i, j, v)<td>Set element in row i and column j to value v
+ * <tr><td>x.get(i)<td>Get the ith element of the matrix (traversing rows first).
+ * <tr><td>x.put(i, v)<td>Set the ith element of the matrix (traversing rows first).
+ * <tr><td>x.getColumn(i)<td>Get a copy of column i.
+ * <tr><td>x.putColumn(i, c)<td>Put matrix c into column i.
+ * <tr><td>x.getRow(i)<td>Get a copy of row i.
+ * <tr><td>x.putRow(i, c)<td>Put matrix c into row i.
+ * <tr><td>x.swapColumns(i, j)<td>Swap the contents of columns i and j.
+ * <tr><td>x.swapRows(i, j)<td>Swap the contents of columns i and j.
+ * </table>
+ *
+ * <p>For <tt>get</tt> and <tt>put</tt>, you can also pass integer arrays,
+ * FloatMatrix objects, or Range objects, which then specify the indices used
+ * as follows:
+ *
+ * <ul>
+ * <li><em>integer array:</em> the elements will be used as indices.
+ * <li><em>FloatMatrix object:</em> non-zero entries specify the indices.
+ * <li><em>Range object:</em> see below.
+ * </ul>
+ *
+ * <p>When using <tt>put</tt> with multiple indices, the assigned object must
+ * have the correct size or be a scalar.</p>
+ *
+ * <p>There exist the following Range objects. The Class <tt>RangeUtils</tt> also
+ * contains the a number of handy helper methods for constructing these ranges.</p>
+ * <table class="my">
+ * <tr><th>Class <th>RangeUtils method <th>Indices
+ * <tr><td>AllRange <td>all() <td>All legal indices.
+ * <tr><td>PointRange <td>point(i) <td> A single point.
+ * <tr><td>IntervalRange <td>interval(a, b)<td> All indices from a to b (inclusive)
+ * <tr><td rowspan=3>IndicesRange <td>indices(int[])<td> The specified indices.
+ * <tr><td>indices(FloatMatrix)<td>The specified indices.
+ * <tr><td>find(FloatMatrix)<td>The non-zero entries of the matrix.
+ * </table>
+ *
+ * <p>The following methods can be used for duplicating and copying matrices.</p>
+ *
+ * <table class="my">
+ * <tr><th>Method<th>Description
+ * <tr><td>x.dup()<td>Get a copy of x.
+ * <tr><td>x.copy(y)<td>Copy the contents of y to x (possible resizing x).
+ * </table>
+ *
+ * <h3>Size and Shape</h3>
+ *
+ * <p>The following methods permit to acces the size of a matrix and change its size or shape.</p>
+ *
+ * <table class="my">
+ * <tr><th>x.Method<th>Description
+ * <tr><td>x.rows<td>Number of rows.
+ * <tr><td>x.columns<td>Number of columns.
+ * <tr><td>x.length<td>Total number of elements.
+ * <tr><td>x.isEmpty()<td>Checks whether rows == 0 and columns == 0.
+ * <tr><td>x.isRowVector()<td>Checks whether rows == 1.
+ * <tr><td>x.isColumnVector()<td>Checks whether columns == 1.
+ * <tr><td>x.isVector()<td>Checks whether rows == 1 or columns == 1.
+ * <tr><td>x.isSquare()<td>Checks whether rows == columns.
+ * <tr><td>x.isScalar()<td>Checks whether length == 1.
+ * <tr><td>x.resize(r, c)<td>Resize the matrix to r rows and c columns, discarding the content.
+ * <tr><td>x.reshape(r, c)<td>Resize the matrix to r rows and c columns.<br> Number of elements must not change.
+ * </table>
+ *
+ * <p>The size is stored in the <tt>rows</tt> and <tt>columns</tt> member variables.
+ * The total number of elements is stored in <tt>length</tt>. Do not change these
+ * values unless you know what you're doing!</p>
+ *
+ * <h3>Arithmetics</h3>
+ *
+ * <p>The usual arithmetic operations are implemented. Each operation exists in a
+ * in-place version, recognizable by the suffix <tt>"i"</tt>, to which you can supply
+ * the result matrix (or <tt>this</tt> is used, if missing). Using in-place operations
+ * can also lead to a smaller memory footprint, as the number of temporary objects
+ * which are directly garbage collected again is reduced.</p>
+ *
+ * <p>Whenever you specify a result vector, the result vector must already have the
+ * correct dimensions.</p>
+ *
+ * <p>For example, you can add two matrices using the <tt>add</tt> method. If you want
+ * to store the result in of <tt>x + y</tt> in <tt>z</tt>, type
+ * <span class=code>
+ * x.addi(y, z) // computes x = y + z.
+ * </span>
+ * Even in-place methods return the result, such that you can easily chain in-place methods,
+ * for example:
+ * <span class=code>
+ * x.addi(y).addi(z) // computes x += y; x += z
+ * </span></p>
+ *
+ * <p>Methods which operate element-wise only make sure that the length of the matrices
+ * is correct. Therefore, you can add a 3 * 3 matrix to a 1 * 9 matrix, for example.</p>
+ *
+ * <p>Finally, there exist versions which take floats instead of FloatMatrix Objects
+ * as arguments. These then compute the operation with the same value as the
+ * right-hand-side. The same effect can be achieved by passing a FloatMatrix with
+ * exactly one element.</p>
+ *
+ * <table class="my">
+ * <tr><th>Operation <th>Method <th>Comment
+ * <tr><td>x + y <td>x.add(y) <td>
+ * <tr><td>x - y <td>x.sub(y), y.rsub(x) <td>rsub subtracts left from right hand side
+ * <tr><td rowspan=3>x * y <td>x.mul(y) <td>element-wise multiplication
+ * <tr> <td>x.mmul(y)<td>matrix-matrix multiplication
+ * <tr> <td>x.dot(y) <td>scalar-product
+ * <tr><td>x / y <td>x.div(y), y.rdiv(x) <td>rdiv divides right hand side by left hand side.
+ * <tr><td>- x <td>x.neg() <td>
+ * </table>
+ *
+ * <p>There also exist operations which work on whole columns or rows.</p>
+ *
+ * <table class="my">
+ * <tr><th>Method <th>Description
+ * <tr><td>x.addRowVector<td>adds a vector to each row (addiRowVector works in-place)
+ * <tr><td>x.addColumnVector<td>adds a vector to each column
+ * <tr><td>x.subRowVector<td>subtracts a vector from each row
+ * <tr><td>x.subColumnVector<td>subtracts a vector from each column
+ * <tr><td>x.mulRow<td>Multiplies a row by a scalar
+ * <tr><td>x.mulColumn<td>multiplies a row by a column
+ * </table>
+ *
+ * <p>In principle, you could achieve the same result by first calling getColumn(),
+ * adding, and then calling putColumn, but these methods are much faster.</p>
+ *
+ * <p>The following comparison operations are available</p>
+ *
+ * <table class="my">
+ * <tr><th>Operation <th>Method
+ * <tr><td>x < y <td>x.lt(y)
+ * <tr><td>x <= y <td>x.le(y)
+ * <tr><td>x > y <td>x.gt(y)
+ * <tr><td>x >= y <td>x.ge(y)
+ * <tr><td>x == y <td>x.eq(y)
+ * <tr><td>x != y <td>x.ne(y)
+ * </table>
+ *
+ * <p> Logical operations are also supported. For these operations, a value different from
+ * zero is treated as "true" and zero is treated as "false". All operations are carried
+ * out elementwise.</p>
+ *
+ * <table class="my">
+ * <tr><th>Operation <th>Method
+ * <tr><td>x & y <td>x.and(y)
+ * <tr><td>x | y <td>x.or(y)
+ * <tr><td>x ^ y <td>x.xor(y)
+ * <tr><td>! x <td>x.not()
+ * </table>
+ *
+ * <p>Finally, there are a few more methods to compute various things:</p>
+ *
+ * <table class="my">
+ * <tr><th>Method <th>Description
+ * <tr><td>x.max() <td>Return maximal element
+ * <tr><td>x.argmax() <td>Return index of largest element
+ * <tr><td>x.min() <td>Return minimal element
+ * <tr><td>x.argmin() <td>Return index of largest element
+ * <tr><td>x.columnMins() <td>Return column-wise minima
+ * <tr><td>x.columnArgmins() <td>Return column-wise index of minima
+ * <tr><td>x.columnMaxs() <td>Return column-wise maxima
+ * <tr><td>x.columnArgmaxs() <td>Return column-wise index of maxima
+ * </table>
+ *
+ * @author Mikio Braun, Johannes Schaback
+ */
+public class FloatMatrix {
+
+ /** Number of rows. */
+ public int rows;
+ /** Number of columns. */
+ public int columns;
+ /** Total number of elements (for convenience). */
+ public int length;
+ /** The actual data stored by rows (that is, row 0, row 1...). */
+ public float[] data = null; // rows are contiguous
+ public static final FloatMatrix EMPTY = new FloatMatrix();
+
+ /**************************************************************************
+ *
+ * Constructors and factory functions
+ *
+ **************************************************************************/
+ /** Create a new matrix with <i>newRows</i> rows, <i>newColumns</i> columns
+ * using <i>newData></i> as the data. The length of the data is not checked!
+ */
+ public FloatMatrix(int newRows, int newColumns, float... newData) {
+ rows = newRows;
+ columns = newColumns;
+ length = rows * columns;
+
+ if (newData != null && newData.length != newRows * newColumns) {
+ throw new IllegalArgumentException(
+ "Passed data must match matrix dimensions.");
+ }
+
+ data = newData;
+ //System.err.printf("%d * %d matrix created\n", rows, columns);
+ }
+
+ /**
+ * Creates a new <i>n</i> times <i>m</i> <tt>FloatMatrix</tt>.
+ * @param newRows the number of rows (<i>n</i>) of the new matrix.
+ * @param newColumns the number of columns (<i>m</i>) of the new matrix.
+ */
+ public FloatMatrix(int newRows, int newColumns) {
+ this(newRows, newColumns, new float[newRows * newColumns]);
+ }
+
+ /**
+ * Creates a new <tt>FloatMatrix</tt> of size 0 times 0.
+ */
+ public FloatMatrix() {
+ this(0, 0, (float[]) null);
+ }
+
+ /**
+ * Create a Matrix of length <tt>len</tt>. By default, this creates a row vector.
+ * @param len
+ */
+ public FloatMatrix(int len) {
+ this(len, 1, new float[len]);
+ }
+
+ public FloatMatrix(float[] newData) {
+ this(newData.length);
+ data = newData;
+ }
+
+ /**
+ * Creates a new matrix by reading it from a file.
+ * @param filename the path and name of the file to read the matrix from
+ * @throws IOException
+ */
+ public FloatMatrix(String filename) throws IOException {
+ load(filename);
+ }
+
+ /**
+ * Creates a new <i>n</i> times <i>m</i> <tt>FloatMatrix</tt> from
+ * the given <i>n</i> times <i>m</i> 2D data array. The first dimension of the array makes the
+ * rows (<i>n</i>) and the second dimension the columns (<i>m</i>). For example, the
+ * given code <br/><br/>
+ * <code>new FloatMatrix(new float[][]{{1d, 2d, 3d}, {4d, 5d, 6d}, {7d, 8d, 9d}}).print();</code><br/><br/>
+ * will constructs the following matrix:
+ * <pre>
+ * 1.0f 2.0f 3.0f
+ * 4.0f 5.0f 6.0f
+ * 7.0f 8.0f 9.0f
+ * </pre>.
+ * @param data <i>n</i> times <i>m</i> data array
+ */
+ public FloatMatrix(float[][] data) {
+ this(data.length, data[0].length);
+
+ for (int r = 0; r < rows; r++) {
+ assert (data[r].length == columns);
+ }
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ put(r, c, data[r][c]);
+ }
+ }
+ }
+
+ /** Create matrix with random values uniformly in 0..1. */
+ public static FloatMatrix rand(int rows, int columns) {
+ FloatMatrix m = new FloatMatrix(rows, columns);
+
+ java.util.Random r = new java.util.Random();
+ for (int i = 0; i < rows * columns; i++) {
+ m.data[i] = r.nextFloat();
+ }
+
+ return m;
+ }
+
+ /** Creates a row vector with random values uniformly in 0..1. */
+ public static FloatMatrix rand(int len) {
+ return rand(len, 1);
+ }
+
+ /** Create matrix with normally distributed random values. */
+ public static FloatMatrix randn(int rows, int columns) {
+ FloatMatrix m = new FloatMatrix(rows, columns);
+
+ java.util.Random r = new java.util.Random();
+ for (int i = 0; i < rows * columns; i++) {
+ m.data[i] = (float) r.nextGaussian();
+ }
+
+ return m;
+ }
+
+ /** Create row vector with normally distributed random values. */
+ public static FloatMatrix randn(int len) {
+ return randn(len, 1);
+ }
+
+ /** Creates a new matrix in which all values are equal 0. */
+ public static FloatMatrix zeros(int rows, int columns) {
+ return new FloatMatrix(rows, columns);
+ }
+
+ /** Creates a row vector of given length. */
+ public static FloatMatrix zeros(int length) {
+ return zeros(length, 1);
+ }
+
+ /** Creates a new matrix in which all values are equal 1. */
+ public static FloatMatrix ones(int rows, int columns) {
+ FloatMatrix m = new FloatMatrix(rows, columns);
+
+ for (int i = 0; i < rows * columns; i++) {
+ m.put(i, 1.0f);
+ }
+
+ return m;
+ }
+
+ /** Creates a row vector with all elements equal to 1. */
+ public static FloatMatrix ones(int length) {
+ return ones(length, 1);
+ }
+
+ /** Construct a new n-by-n identity matrix. */
+ public static FloatMatrix eye(int n) {
+ FloatMatrix m = new FloatMatrix(n, n);
+
+ for (int i = 0; i < n; i++) {
+ m.put(i, i, 1.0f);
+ }
+
+ return m;
+ }
+
+ /**
+ * Creates a new matrix where the values of the given vector are the diagonal values of
+ * the matrix.
+ */
+ public static FloatMatrix diag(FloatMatrix x) {
+ FloatMatrix m = new FloatMatrix(x.length, x.length);
+
+ for (int i = 0; i < x.length; i++) {
+ m.put(i, i, x.get(i));
+ }
+
+ return m;
+ }
+
+ /**
+ * Create a 1-by-1 matrix. For many operations, this matrix functions like a
+ * normal float.
+ */
+ public static FloatMatrix scalar(float s) {
+ FloatMatrix m = new FloatMatrix(1, 1);
+ m.put(0, 0, s);
+ return m;
+ }
+
+ /** Test whether a matrix is scalar. */
+ public boolean isScalar() {
+ return length == 1;
+ }
+
+ /** Return the first element of the matrix. */
+ public float scalar() {
+ return get(0);
+ }
+
+ /**
+ * Concatenates two matrices horizontally. Matrices must have identical
+ * numbers of rows.
+ */
+ public static FloatMatrix concatHorizontally(FloatMatrix A, FloatMatrix B) {
+ if (A.rows != B.rows) {
+ throw new SizeException("Matrices don't have same number of rows.");
+ }
+
+ FloatMatrix result = new FloatMatrix(A.rows, A.columns + B.columns);
+ SimpleBlas.copy(A, result);
+ JavaBlas.rcopy(B.length, B.data, 0, 1, result.data, A.length, 1);
+ return result;
+ }
+
+ /**
+ * Concatenates two matrices vertically. Matrices must have identical
+ * numbers of columns.
+ */
+ public static FloatMatrix concatVertically(FloatMatrix A, FloatMatrix B) {
+ if (A.columns != B.columns) {
+ throw new SizeException("Matrices don't have same number of columns (" + A.columns + " != " + B.columns + ".");
+ }
+
+ FloatMatrix result = new FloatMatrix(A.rows + B.rows, A.columns);
+
+ for (int i = 0; i < A.columns; i++) {
+ JavaBlas.rcopy(A.rows, A.data, A.index(0, i), 1, result.data, result.index(0, i), 1);
+ JavaBlas.rcopy(B.rows, B.data, B.index(0, i), 1, result.data, result.index(A.rows, i), 1);
+ }
+
+ return result;
+ }
+
+ /**************************************************************************
+ * Working with slices (Man! 30+ methods just to make this a bit flexible...)
+ */
+ /** Get all elements specified by the linear indices. */
+ public FloatMatrix get(int[] indices) {
+ FloatMatrix result = new FloatMatrix(indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ result.put(i, get(indices[i]));
+ }
+
+ return result;
+ }
+
+ /** Get all elements for a given row and the specified columns. */
+ public FloatMatrix get(int r, int[] indices) {
+ FloatMatrix result = new FloatMatrix(1, indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ result.put(i, get(r, indices[i]));
+ }
+
+ return result;
+ }
+
+ /** Get all elements for a given column and the specified rows. */
+ public FloatMatrix get(int[] indices, int c) {
+ FloatMatrix result = new FloatMatrix(indices.length, c);
+
+ for (int i = 0; i < indices.length; i++) {
+ result.put(i, get(indices[i], c));
+ }
+
+ return result;
+ }
+
+ /** Get all elements from the specified rows and columns. */
+ public FloatMatrix get(int[] rindices, int[] cindices) {
+ FloatMatrix result = new FloatMatrix(rindices.length, cindices.length);
+
+ for (int i = 0; i < rindices.length; i++) {
+ for (int j = 0; j < cindices.length; j++) {
+ result.put(i, j, get(rindices[i], cindices[j]));
+ }
+ }
+
+ return result;
+ }
+
+ /** Get elements from specified rows and columns. */
+ public FloatMatrix get(Range rs, Range cs) {
+ rs.init(0, rows - 1);
+ cs.init(0, columns - 1);
+ FloatMatrix result = new FloatMatrix(rs.length(), cs.length());
+
+ for (; !rs.hasMore(); rs.next()) {
+ for (; !cs.hasMore(); cs.next()) {
+ result.put(rs.index(), cs.index(), get(rs.value(), cs.value()));
+ }
+ }
+
+ return result;
+ }
+
+ /** Get elements specified by the non-zero entries of the passed matrix. */
+ public FloatMatrix get(FloatMatrix indices) {
+ return get(indices.findIndices());
+ }
+
+ /**
+ * Get elements from a row and columns as specified by the non-zero entries of
+ * a matrix.
+ */
+ public FloatMatrix get(int r, FloatMatrix indices) {
+ return get(r, indices.findIndices());
+ }
+
+ /**
+ * Get elements from a column and rows as specified by the non-zero entries of
+ * a matrix.
+ */
+ public FloatMatrix get(FloatMatrix indices, int c) {
+ return get(indices.findIndices(), c);
+ }
+
+ /**
+ * Get elements from columns and rows as specified by the non-zero entries of
+ * the passed matrices.
+ */
+ public FloatMatrix get(FloatMatrix rindices, FloatMatrix cindices) {
+ return get(rindices.findIndices(), cindices.findIndices());
+ }
+
+ /** Return all elements with linear index a, a + 1, ..., b - 1.*/
+ public FloatMatrix getRange(int a, int b) {
+ FloatMatrix result = new FloatMatrix(b - a);
+
+ for (int k = 0; k < b - a; k++) {
+ result.put(k, get(a + k));
+ }
+
+ return result;
+ }
+
+ /** Get elements from a row and columns <tt>a</tt> to <tt>b</tt>. */
+ public FloatMatrix getColumnRange(int r, int a, int b) {
+ FloatMatrix result = new FloatMatrix(1, b - a);
+
+ for (int k = 0; k < b - a; k++) {
+ result.put(k, get(r, a + k));
+ }
+
+ return result;
+ }
+
+ /** Get elements from a column and rows <tt>a/tt> to <tt>b</tt>. */
+ public FloatMatrix getRowRange(int a, int b, int c) {
+ FloatMatrix result = new FloatMatrix(b - a);
+
+ for (int k = 0; k < b - a; k++) {
+ result.put(k, get(a + k, c));
+ }
+
+ return result;
+ }
+
+ /**
+ * Get elements from rows <tt>ra</tt> to <tt>rb</tt> and
+ * columns <tt>ca</tt> to <tt>cb</tt>.
+ */
+ public FloatMatrix getRange(int ra, int rb, int ca, int cb) {
+ FloatMatrix result = new FloatMatrix(rb - ra, cb - ca);
+
+ for (int i = 0; i < rb - ra; i++) {
+ for (int j = 0; j < cb - ca; j++) {
+ result.put(i, j, get(ra + i, ca + j));
+ }
+ }
+
+ return result;
+ }
+
+ /** Get whole rows from the passed indices. */
+ public FloatMatrix getRows(int[] rindices) {
+ FloatMatrix result = new FloatMatrix(rindices.length, columns);
+ for (int i = 0; i < rindices.length; i++) {
+ JavaBlas.rcopy(columns, data, index(rindices[i], 0), rows, result.data, result.index(i, 0), result.rows);
+ }
+ return result;
+ }
+
+ /** Get whole rows as specified by the non-zero entries of a matrix. */
+ public FloatMatrix getRows(FloatMatrix rindices) {
+ return getRows(rindices.findIndices());
+ }
+
+ /** Get whole columns from the passed indices. */
+ public FloatMatrix getColumns(int[] cindices) {
+ FloatMatrix result = new FloatMatrix(rows, cindices.length);
+ for (int i = 0; i < cindices.length; i++) {
+ JavaBlas.rcopy(rows, data, index(0, cindices[i]), 1, result.data, result.index(0, i), 1);
+ }
+ return result;
+ }
+
+ /** Get whole columns as specified by the non-zero entries of a matrix. */
+ public FloatMatrix getColumns(FloatMatrix cindices) {
+ return getColumns(cindices.findIndices());
+ }
+
+ /**
+ * Assert that the matrix has a certain length.
+ * @throws SizeException
+ */
+ public void checkLength(int l) {
+ if (length != l) {
+ throw new SizeException("Matrix does not have the necessary length (" + length + " != " + l + ").");
+ }
+ }
+
+ /**
+ * Asserts that the matrix has a certain number of rows.
+ * @throws SizeException
+ */
+ public void checkRows(int r) {
+ if (rows != r) {
+ throw new SizeException("Matrix does not have the necessary number of rows (" + rows + " != " + r + ").");
+ }
+ }
+
+ /**
+ * Asserts that the amtrix has a certain number of columns.
+ * @throws SizeException
+ */
+ public void checkColumns(int c) {
+ if (columns != c) {
+ throw new SizeException("Matrix does not have the necessary number of columns (" + columns + " != " + c + ").");
+ }
+ }
+
+ /** Set elements in linear ordering in the specified indices. */
+ public FloatMatrix put(int[] indices, FloatMatrix x) {
+ if (x.isScalar()) {
+ return put(indices, x.scalar());
+ }
+ x.checkLength(indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ put(indices[i], x.get(i));
+ }
+
+ return this;
+ }
+
+ /** Set multiple elements in a row. */
+ public FloatMatrix put(int r, int[] indices, FloatMatrix x) {
+ if (x.isScalar()) {
+ return put(r, indices, x.scalar());
+ }
+ x.checkColumns(indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ put(r, indices[i], x.get(i));
+ }
+
+ return this;
+ }
+
+ /** Set multiple elements in a row. */
+ public FloatMatrix put(int[] indices, int c, FloatMatrix x) {
+ if (x.isScalar()) {
+ return put(indices, c, x.scalar());
+ }
+ x.checkRows(indices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ put(indices[i], c, x.get(i));
+ }
+
+ return this;
+ }
+
+ /** Put a sub-matrix as specified by the indices. */
+ public FloatMatrix put(int[] rindices, int[] cindices, FloatMatrix x) {
+ if (x.isScalar()) {
+ return put(rindices, cindices, x.scalar());
+ }
+ x.checkRows(rindices.length);
+ x.checkColumns(cindices.length);
+
+ for (int i = 0; i < rindices.length; i++) {
+ for (int j = 0; j < cindices.length; j++) {
+ put(rindices[i], cindices[j], x.get(i, j));
+ }
+ }
+
+ return this;
+ }
+
+ /** Put a matrix into specified indices. */
+ public FloatMatrix put(Range rs, Range cs, FloatMatrix x) {
+ rs.init(0, rows - 1);
+ cs.init(0, columns - 1);
+
+ x.checkRows(rs.length());
+ x.checkColumns(cs.length());
+
+ for (; rs.hasMore(); rs.next()) {
+ for (; cs.hasMore(); cs.next()) {
+ put(rs.value(), cs.value(), x.get(rs.index(), cs.index()));
+ }
+ }
+
+ return this;
+ }
+
+ /** Put a single value into the specified indices (linear adressing). */
+ public FloatMatrix put(int[] indices, float v) {
+ for (int i = 0; i < indices.length; i++) {
+ put(indices[i], v);
+ }
+
+ return this;
+ }
+
+ /** Put a single value into a row and the specified columns. */
+ public FloatMatrix put(int r, int[] indices, float v) {
+ for (int i = 0; i < indices.length; i++) {
+ put(r, indices[i], v);
+ }
+
+ return this;
+ }
+
+ /** Put a single value into the specified rows of a column. */
+ public FloatMatrix put(int[] indices, int c, float v) {
+ for (int i = 0; i < indices.length; i++) {
+ put(indices[i], c, v);
+ }
+
+ return this;
+ }
+
+ /** Put a single value into the specified rows and columns. */
+ public FloatMatrix put(int[] rindices, int[] cindices, float v) {
+ for (int i = 0; i < rindices.length; i++) {
+ for (int j = 0; j < cindices.length; j++) {
+ put(rindices[i], cindices[j], v);
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Put a sub-matrix into the indices specified by the non-zero entries
+ * of <tt>indices</tt> (linear adressing).
+ */
+ public FloatMatrix put(FloatMatrix indices, FloatMatrix v) {
+ return put(indices.findIndices(), v);
+ }
+
+ /** Put a sub-vector into the specified columns (non-zero entries of <tt>indices</tt>) of a row. */
+ public FloatMatrix put(int r, FloatMatrix indices, FloatMatrix v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ /** Put a sub-vector into the specified rows (non-zero entries of <tt>indices</tt>) of a column. */
+ public FloatMatrix put(FloatMatrix indices, int c, FloatMatrix v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ /**
+ * Put a sub-matrix into the specified rows and columns (non-zero entries of
+ * <tt>rindices</tt> and <tt>cindices</tt>.
+ */
+ public FloatMatrix put(FloatMatrix rindices, FloatMatrix cindices, FloatMatrix v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ /**
+ * Put a single value into the elements specified by the non-zero
+ * entries of <tt>indices</tt> (linear adressing).
+ */
+ public FloatMatrix put(FloatMatrix indices, float v) {
+ return put(indices.findIndices(), v);
+ }
+
+ /**
+ * Put a single value into the specified columns (non-zero entries of
+ * <tt>indices</tt>) of a row.
+ */
+ public FloatMatrix put(int r, FloatMatrix indices, float v) {
+ return put(r, indices.findIndices(), v);
+ }
+
+ /**
+ * Put a single value into the specified rows (non-zero entries of
+ * <tt>indices</tt>) of a column.
+ */
+ public FloatMatrix put(FloatMatrix indices, int c, float v) {
+ return put(indices.findIndices(), c, v);
+ }
+
+ /**
+ * Put a single value in the specified rows and columns (non-zero entries
+ * of <tt>rindices</tt> and <tt>cindices</tt>.
+ */
+ public FloatMatrix put(FloatMatrix rindices, FloatMatrix cindices, float v) {
+ return put(rindices.findIndices(), cindices.findIndices(), v);
+ }
+
+ /** Find the linear indices of all non-zero elements. */
+ public int[] findIndices() {
+ int len = 0;
+ for (int i = 0; i < length; i++) {
+ if (get(i) != 0.0f) {
+ len++;
+ }
+ }
+
+ int[] indices = new int[len];
+ int c = 0;
+
+ for (int i = 0; i < length; i++) {
+ if (get(i) != 0.0f) {
+ indices[c++] = i;
+ }
+ }
+
+ return indices;
+ }
+
+ /**************************************************************************
+ * Basic operations (copying, resizing, element access)
+ */
+ /** Return transposed copy of this matrix. */
+ public FloatMatrix transpose() {
+ FloatMatrix result = new FloatMatrix(columns, rows);
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < columns; j++) {
+ result.put(j, i, get(i, j));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Compare two matrices. Returns true if and only if other is also a
+ * FloatMatrix which has the same size and the maximal absolute
+ * difference in matrix elements is smaller thatn 1e-6.
+ */
+ public boolean equals(Object o) {
+ if (!(o instanceof FloatMatrix)) {
+ return false;
+ }
+
+ FloatMatrix other = (FloatMatrix) o;
+
+ if (!sameSize(other)) {
+ return false;
+ }
+
+ FloatMatrix diff = MatrixFunctions.absi(sub(other));
+
+ return diff.max() / (rows * columns) < 1e-6;
+ }
+
+ /** Resize the matrix. All elements will be set to zero. */
+ public void resize(int newRows, int newColumns) {
+ rows = newRows;
+ columns = newColumns;
+ length = newRows * newColumns;
+ data = new float[rows * columns];
+ }
+
+ /** Reshape the matrix. Number of elements must not change. */
+ public FloatMatrix reshape(int newRows, int newColumns) {
+ if (length != newRows * newColumns) {
+ throw new IllegalArgumentException(
+ "Number of elements must not change.");
+ }
+
+ rows = newRows;
+ columns = newColumns;
+
+ return this;
+ }
+
+ /** Generate a new matrix which has the given number of replications of this. */
+ public FloatMatrix repmat(int rowMult, int columnMult) {
+ FloatMatrix result = new FloatMatrix(rows * rowMult, columns * columnMult);
+
+ for (int c = 0; c < columnMult; c++)
+ for (int r = 0; r < rowMult; r++)
+ for (int i = 0; i < rows; i++)
+ for (int j = 0; j < columns; j++)
+ result.put(r * rows + i, c * columns + j, get(i, j));
+ return result;
+ }
+
+ /** Checks whether two matrices have the same size. */
+ public boolean sameSize(FloatMatrix a) {
+ return rows == a.rows && columns == a.columns;
+ }
+
+ /** Throws SizeException unless two matrices have the same size. */
+ public void assertSameSize(FloatMatrix a) {
+ if (!sameSize(a)) {
+ throw new SizeException("Matrices must have the same size.");
+ }
+ }
+
+ /** Checks whether two matrices can be multiplied (that is, number of columns of
+ * this must equal number of rows of a. */
+ public boolean multipliesWith(FloatMatrix a) {
+ return columns == a.rows;
+ }
+
+ /** Throws SizeException unless matrices can be multiplied with one another. */
+ public void assertMultipliesWith(FloatMatrix a) {
+ if (!multipliesWith(a)) {
+ throw new SizeException("Number of columns of left matrix must be equal to number of rows of right matrix.");
+ }
+ }
+
+ /** Checks whether two matrices have the same length. */
+ public boolean sameLength(FloatMatrix a) {
+ return length == a.length;
+ }
+
+ /** Throws SizeException unless matrices have the same length. */
+ public void assertSameLength(FloatMatrix a) {
+ if (!sameLength(a)) {
+ throw new SizeException("Matrices must have same length (is: " + length + " and " + a.length + ")");
+ }
+ }
+
+ /** Copy FloatMatrix a to this. this a is resized if necessary. */
+ public FloatMatrix copy(FloatMatrix a) {
+ if (!sameSize(a)) {
+ resize(a.rows, a.columns);
+ }
+
+ System.arraycopy(data, 0, a.data, 0, length);
+ return a;
+ }
+
+ /**
+ * Returns a duplicate of this matrix. Geometry is the same (including offsets, transpose, etc.),
+ * but the buffer is not shared.
+ */
+ public FloatMatrix dup() {
+ FloatMatrix out = new FloatMatrix(rows, columns);
+
+ JavaBlas.rcopy(length, data, 0, 1, out.data, 0, 1);
+
+ return out;
+ }
+
+ /** Swap two columns of a matrix. */
+ public FloatMatrix swapColumns(int i, int j) {
+ Blas.sswap(rows, data, index(0, i), 1, data, index(0, j), 1);
+ return this;
+ }
+
+ /** Swap two rows of a matrix. */
+ public FloatMatrix swapRows(int i, int j) {
+ Blas.sswap(columns, data, index(i, 0), rows, data, index(j, 0), rows);
+ return this;
+ }
+
+ /** Set matrix element */
+ public FloatMatrix put(int rowIndex, int columnIndex, float value) {
+ data[index(rowIndex, columnIndex)] = value;
+ return this;
+ }
+
+ /** Retrieve matrix element */
+ public float get(int rowIndex, int columnIndex) {
+ return data[index(rowIndex, columnIndex)];
+ }
+
+ /** Get index of an element */
+ public int index(int rowIndex, int columnIndex) {
+ return rowIndex + rows * columnIndex;
+ }
+
+ /** Compute the row index of a linear index. */
+ public int indexRows(int i) {
+ return i / rows;
+ }
+
+ /** Compute the column index of a linear index. */
+ public int indexColumns(int i) {
+ return i - indexRows(i) * rows;
+ }
+
+ /** Get a matrix element (linear indexing). */
+ public float get(int i) {
+ return data[i];
+ }
+
+ /** Set a matrix element (linear indexing). */
+ public FloatMatrix put(int i, float v) {
+ data[i] = v;
+ return this;
+ }
+
+ /** Set all elements to a value. */
+ public FloatMatrix fill(float value) {
+ for (int i = 0; i < length; i++) {
+ put(i, value);
+ }
+ return this;
+ }
+
+ /** Get number of rows. */
+ public int getRows() {
+ return rows;
+ }
+
+ /** Get number of columns. */
+ public int getColumns() {
+ return columns;
+ }
+
+ /** Get total number of elements. */
+ public int getLength() {
+ return length;
+ }
+
+ /** Checks whether the matrix is empty. */
+ public boolean isEmpty() {
+ return columns == 0 || rows == 0;
+ }
+
+ /** Checks whether the matrix is square. */
+ public boolean isSquare() {
+ return columns == rows;
+ }
+
+ /** Throw SizeException unless matrix is square. */
+ public void assertSquare() {
+ if (!isSquare()) {
+ throw new SizeException("Matrix must be square!");
+ }
+ }
+
+ /** Checks whether the matrix is a vector. */
+ public boolean isVector() {
+ return columns == 1 || rows == 1;
+ }
+
+ /** Checks whether the matrix is a row vector. */
+ public boolean isRowVector() {
+ return rows == 1;
+ }
+
+ /** Checks whether the matrix is a column vector. */
+ public boolean isColumnVector() {
+ return columns == 1;
+ }
+
+ /** Returns the diagonal of the matrix. */
+ public FloatMatrix diag() {
+ assertSquare();
+ FloatMatrix d = new FloatMatrix(rows);
+ JavaBlas.rcopy(rows, data, 0, rows + 1, d.data, 0, 1);
+ return d;
+ }
+
+ /** Pretty-print this matrix to <tt>System.out</tt>. */
+ public void print() {
+ System.out.println(toString());
+ }
+
+ /** Generate string representation of the matrix. */
+ @Override
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+
+ s.append("[");
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < columns; j++) {
+ s.append(get(i, j));
+ if (j < columns - 1) {
+ s.append(", ");
+ }
+ }
+ if (i < rows - 1) {
+ s.append("; ");
+ }
+ }
+
+ s.append("]");
+
+ return s.toString();
+ }
+
+ /**
+ * Generate string representation of the matrix, with specified
+ * format for the entries. For example, <code>x.toString("%.1f")</code>
+ * generates a string representations having only one position after the
+ * decimal point.
+ */
+ public String toString(String fmt) {
+ StringWriter s = new StringWriter();
+ PrintWriter p = new PrintWriter(s);
+
+ p.print("[");
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ p.printf(fmt, get(r, c));
+ if (c < columns - 1) {
+ p.print(", ");
+ }
+ }
+ if (r < rows - 1) {
+ p.print("; ");
+ }
+ }
+
+ p.print("]");
+
+ return s.toString();
+ }
+
+ /** Converts the matrix to a one-dimensional array of floats. */
+ public float[] toArray() {
+ float[] array = new float[length];
+
+ System.arraycopy(data, 0, array, 0, length);
+
+ return array;
+ }
+
+ /** Converts the matrix to a two-dimensional array of floats. */
+ public float[][] toArray2() {
+ float[][] array = new float[rows][columns];
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ array[r][c] = get(r, c);
+ }
+ }
+
+ return array;
+ }
+
+ /** Converts the matrix to a one-dimensional array of integers. */
+ public int[] toIntArray() {
+ int[] array = new int[length];
+
+ for (int i = 0; i < length; i++) {
+ array[i] = (int) Math.rint(get(i));
+ }
+
+ return array;
+ }
+
+ /** Convert the matrix to a two-dimensional array of integers. */
+ public int[][] toIntArray2() {
+ int[][] array = new int[rows][columns];
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ array[r][c] = (int) Math.rint(get(r, c));
+ }
+ }
+
+ return array;
+ }
+
+ /** Convert the matrix to a one-dimensional array of boolean values. */
+ public boolean[] toBooleanArray() {
+ boolean[] array = new boolean[length];
+
+ for (int i = 0; i < length; i++) {
+ array[i] = get(i) != 0.0f ? true : false;
+ }
+
+ return array;
+ }
+
+ /** Convert the matrix to a two-dimensional array of boolean values. */
+ public boolean[][] toBooleanArray2() {
+ boolean[][] array = new boolean[rows][columns];
+
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < columns; c++) {
+ array[r][c] = get(r, c) != 0.0f ? true : false;
+ }
+ }
+
+ return array;
+ }
+
+ /** Convert matrix to FloatMatrix. */
+ public FloatMatrix toFloatMatrix() {
+ FloatMatrix result = new FloatMatrix(rows, columns);
+
+ for (int c = 0; c < columns; c++) {
+ for (int r = 0; r < rows; r++) {
+ result.put(r, c, (float) get(r, c));
+ }
+ }
+
+ return result;
+ }
+
+ /**************************************************************************
+ * Arithmetic Operations
+ */
+ /**
+ * Ensures that the result vector has the same length as this. If not,
+ * resizing result is tried, which fails if result == this or result == other.
+ */
+ private void ensureResultLength(FloatMatrix other, FloatMatrix result) {
+ if (!sameLength(result)) {
+ if (result == this || result == other) {
+ throw new SizeException("Cannot resize result matrix because it is used in-place.");
+ }
+ result.resize(rows, columns);
+ }
+ }
+
+ /** Add two matrices (in-place). */
+ public FloatMatrix addi(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar()) {
+ return addi(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.addi(scalar(), result);
+ }
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ if (result == this) {
+ SimpleBlas.axpy(1.0f, other, result);
+ } else if (result == other) {
+ SimpleBlas.axpy(1.0f, this, result);
+ } else {
+ /*SimpleBlas.copy(this, result);
+ SimpleBlas.axpy(1.0f, other, result);*/
+ JavaBlas.rzgxpy(length, result.data, data, other.data);
+ }
+
+ return result;
+ }
+
+ /** Add a scalar to a matrix (in-place). */
+ public FloatMatrix addi(float v, FloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) + v);
+ }
+ return result;
+ }
+
+ /** Subtract two matrices (in-place). */
+ public FloatMatrix subi(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar()) {
+ return subi(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.rsubi(scalar(), result);
+ }
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ if (result == this) {
+ SimpleBlas.axpy(-1.0f, other, result);
+ } else if (result == other) {
+ SimpleBlas.scal(-1.0f, result);
+ SimpleBlas.axpy(1.0f, this, result);
+ } else {
+ SimpleBlas.copy(this, result);
+ SimpleBlas.axpy(-1.0f, other, result);
+ }
+ return result;
+ }
+
+ /** Subtract a scalar from a matrix (in-place). */
+ public FloatMatrix subi(float v, FloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) - v);
+ }
+ return result;
+ }
+
+ /**
+ * Subtract two matrices, but subtract first from second matrix, that is,
+ * compute <em>result = other - this</em> (in-place).
+ * */
+ public FloatMatrix rsubi(FloatMatrix other, FloatMatrix result) {
+ return other.subi(this, result);
+ }
+
+ /** Subtract a matrix from a scalar (in-place). */
+ public FloatMatrix rsubi(float a, FloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, a - get(i));
+ }
+ return result;
+ }
+
+ /** Elementwise multiplication (in-place). */
+ public FloatMatrix muli(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar()) {
+ return muli(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.muli(scalar(), result);
+ }
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) * other.get(i));
+ }
+ return result;
+ }
+
+ /** Elementwise multiplication with a scalar (in-place). */
+ public FloatMatrix muli(float v, FloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) * v);
+ }
+ return result;
+ }
+
+ /** Matrix-matrix multiplication (in-place). */
+ public FloatMatrix mmuli(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar()) {
+ return muli(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.muli(scalar(), result);
+ }
+
+ /* check sizes and resize if necessary */
+ assertMultipliesWith(other);
+ if (result.rows != rows || result.columns != other.columns) {
+ if (result != this && result != other) {
+ result.resize(rows, other.columns);
+ } else {
+ throw new SizeException("Cannot resize result matrix because it is used in-place.");
+ }
+ }
+
+ if (result == this || result == other) {
+ /* actually, blas cannot do multiplications in-place. Therefore, we will fake by
+ * allocating a temporary object on the side and copy the result later.
+ */
+ FloatMatrix temp = new FloatMatrix(result.rows, result.columns);
+ if (other.columns == 1) {
+ SimpleBlas.gemv(1.0f, this, other, 0.0f, temp);
+ } else {
+ SimpleBlas.gemm(1.0f, this, other, 0.0f, temp);
+ }
+ SimpleBlas.copy(temp, result);
+ } else {
+ if (other.columns == 1) {
+ SimpleBlas.gemv(1.0f, this, other, 0.0f, result);
+ } else {
+ SimpleBlas.gemm(1.0f, this, other, 0.0f, result);
+ }
+ }
+ return result;
+ }
+
+ /** Matrix-matrix multiplication with a scalar (for symmetry, does the
+ * same as <code>muli(scalar)</code> (in-place).
+ */
+ public FloatMatrix mmuli(float v, FloatMatrix result) {
+ return muli(v, result);
+ }
+
+ /** Elementwise division (in-place). */
+ public FloatMatrix divi(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar()) {
+ return divi(other.scalar(), result);
+ }
+ if (isScalar()) {
+ return other.rdivi(scalar(), result);
+ }
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) / other.get(i));
+ }
+ return result;
+ }
+
+ /** Elementwise division with a scalar (in-place). */
+ public FloatMatrix divi(float a, FloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, get(i) / a);
+ }
+ return result;
+ }
+
+ /**
+ * Elementwise division, with operands switched. Computes
+ * <code>result = other / this</code> (in-place). */
+ public FloatMatrix rdivi(FloatMatrix other, FloatMatrix result) {
+ return other.divi(this, result);
+ }
+
+ /** (Elementwise) division with a scalar, with operands switched. Computes
+ * <code>result = a / this</code> (in-place). */
+ public FloatMatrix rdivi(float a, FloatMatrix result) {
+ ensureResultLength(null, result);
+
+ for (int i = 0; i < length; i++) {
+ result.put(i, a / get(i));
+ }
+ return result;
+ }
+
+ /** Negate each element (in-place). */
+ public FloatMatrix negi() {
+ for (int i = 0; i < length; i++) {
+ put(i, -get(i));
+ }
+ return this;
+ }
+
+ /** Negate each element. */
+ public FloatMatrix neg() {
+ return dup().negi();
+ }
+
+ /** Maps zero to 1.0f and all non-zero values to 0.0f (in-place). */
+ public FloatMatrix noti() {
+ for (int i = 0; i < length; i++) {
+ put(i, get(i) == 0.0f ? 1.0f : 0.0f);
+ }
+ return this;
+ }
+
+ /** Maps zero to 1.0f and all non-zero values to 0.0f. */
+ public FloatMatrix not() {
+ return dup().noti();
+ }
+
+ /** Maps zero to 0.0f and all non-zero values to 1.0f (in-place). */
+ public FloatMatrix truthi() {
+ for (int i = 0; i < length; i++) {
+ put(i, get(i) == 0.0f ? 0.0f : 1.0f);
+ }
+ return this;
+ }
+
+ /** Maps zero to 0.0f and all non-zero values to 1.0f. */
+ public FloatMatrix truth() {
+ return dup().truthi();
+ }
+
+ /****************************************************************
+ * Rank one-updates
+ */
+ /** Computes a rank-1-update A = A + alpha * x * y'. */
+ public FloatMatrix rankOneUpdate(float alpha, FloatMatrix x, FloatMatrix y) {
+ if (rows != x.length) {
+ throw new SizeException("Vector x has wrong length (" + x.length + " != " + rows + ").");
+ }
+ if (columns != y.length) {
+ throw new SizeException("Vector y has wrong length (" + x.length + " != " + columns + ").");
+ }
+
+ SimpleBlas.ger(alpha, x, y, this);
+ return this;
+ }
+
+ /** Computes a rank-1-update A = A + alpha * x * x'. */
+ public FloatMatrix rankOneUpdate(float alpha, FloatMatrix x) {
+ return rankOneUpdate(alpha, x, x);
+ }
+
+ /** Computes a rank-1-update A = A + x * x'. */
+ public FloatMatrix rankOneUpdate(FloatMatrix x) {
+ return rankOneUpdate(1.0f, x, x);
+ }
+
+ /** Computes a rank-1-update A = A + x * y'. */
+ public FloatMatrix rankOneUpdate(FloatMatrix x, FloatMatrix y) {
+ return rankOneUpdate(1.0f, x, y);
+ }
+
+ /****************************************************************
+ * Logical operations
+ */
+ /** Returns the minimal element of the matrix. */
+ public float min() {
+ if (isEmpty()) {
+ return Float.POSITIVE_INFINITY;
+ }
+ float v = Float.POSITIVE_INFINITY;
+ for (int i = 0; i < length; i++) {
+ if (!Float.isNaN(get(i)) && get(i) < v) {
+ v = get(i);
+ }
+ }
+
+ return v;
+ }
+
+ /**
+ * Returns the linear index of the minimal element. If there are
+ * more than one elements with this value, the first one is returned.
+ */
+ public int argmin() {
+ if (isEmpty()) {
+ return -1;
+ }
+ float v = Float.POSITIVE_INFINITY;
+ int a = -1;
+ for (int i = 0; i < length; i++) {
+ if (!Float.isNaN(get(i)) && get(i) < v) {
+ v = get(i);
+ a = i;
+ }
+ }
+
+ return a;
+ }
+
+ /**
+ * Computes the minimum between two matrices. Returns the smaller of the
+ * corresponding elements in the matrix (in-place).
+ */
+ public FloatMatrix mini(FloatMatrix other, FloatMatrix result) {
+ if (result == this) {
+ for (int i = 0; i < length; i++) {
+ if (get(i) > other.get(i)) {
+ put(i, other.get(i));
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (get(i) > other.get(i)) {
+ result.put(i, other.get(i));
+ } else {
+ result.put(i, get(i));
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Computes the minimum between two matrices. Returns the smaller of the
+ * corresponding elements in the matrix (in-place on this).
+ */
+ public FloatMatrix mini(FloatMatrix other) {
+ return mini(other, this);
+ }
+
+ /**
+ * Computes the minimum between two matrices. Returns the smaller of the
+ * corresponding elements in the matrix (in-place on this).
+ */
+ public FloatMatrix min(FloatMatrix other) {
+ return mini(other, new FloatMatrix(rows, columns));
+ }
+
+ public FloatMatrix mini(float v, FloatMatrix result) {
+ if (result == this) {
+ for (int i = 0; i < length; i++) {
+ if (get(i) > v) {
+ result.put(i, v);
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (get(i) > v) {
+ result.put(i, v);
+ } else {
+ result.put(i, get(i));
+ }
+ }
+
+ }
+ return this;
+ }
+
+ public FloatMatrix mini(float v) {
+ return mini(v, this);
+ }
+
+ public FloatMatrix min(float v) {
+ return mini(v, new FloatMatrix(rows, columns));
+ }
+
+ /** Returns the maximal element of the matrix. */
+ public float max() {
+ if (isEmpty()) {
+ return Float.NEGATIVE_INFINITY;
+ }
+ float v = Float.NEGATIVE_INFINITY;
+ for (int i = 0; i < length; i++) {
+ if (!Float.isNaN(get(i)) && get(i) > v) {
+ v = get(i);
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Returns the linear index of the maximal element of the matrix. If
+ * there are more than one elements with this value, the first one
+ * is returned.
+ */
+ public int argmax() {
+ if (isEmpty()) {
+ return -1;
+ }
+ float v = Float.NEGATIVE_INFINITY;
+ int a = -1;
+ for (int i = 0; i < length; i++) {
+ if (!Float.isNaN(get(i)) && get(i) > v) {
+ v = get(i);
+ a = i;
+ }
+ }
+
+ return a;
+ }
+
+ /**
+ * Computes the maximum between two matrices. Returns the larger of the
+ * corresponding elements in the matrix (in-place).
+ */
+ public FloatMatrix maxi(FloatMatrix other, FloatMatrix result) {
+ if (result == this) {
+ for (int i = 0; i < length; i++) {
+ if (get(i) < other.get(i)) {
+ put(i, other.get(i));
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (get(i) < other.get(i)) {
+ result.put(i, other.get(i));
+ } else {
+ result.put(i, get(i));
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Computes the maximum between two matrices. Returns the smaller of the
+ * corresponding elements in the matrix (in-place on this).
+ */
+ public FloatMatrix maxi(FloatMatrix other) {
+ return maxi(other, this);
+ }
+
+ /**
+ * Computes the maximum between two matrices. Returns the larger of the
+ * corresponding elements in the matrix (in-place on this).
+ */
+ public FloatMatrix max(FloatMatrix other) {
+ return maxi(other, new FloatMatrix(rows, columns));
+ }
+
+ public FloatMatrix maxi(float v, FloatMatrix result) {
+ if (result == this) {
+ for (int i = 0; i < length; i++) {
+ if (get(i) < v) {
+ result.put(i, v);
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (get(i) < v) {
+ result.put(i, v);
+ } else {
+ result.put(i, get(i));
+ }
+ }
+
+ }
+ return this;
+ }
+
+ public FloatMatrix maxi(float v) {
+ return maxi(v, this);
+ }
+
+ public FloatMatrix max(float v) {
+ return maxi(v, new FloatMatrix(rows, columns));
+ }
+
+ /** Computes the sum of all elements of the matrix. */
+ public float sum() {
+ float s = 0.0f;
+ for (int i = 0; i < length; i++) {
+ s += get(i);
+ }
+ return s;
+ }
+
+ /**
+ * Computes the mean value of all elements in the matrix,
+ * that is, <code>x.sum() / x.length</code>.
+ */
+ public float mean() {
+ return sum() / length;
+ }
+
+ /**
+ * Computes the cumulative sum, that is, the sum of all elements
+ * of the matrix up to a given index in linear addressing (in-place).
+ */
+ public FloatMatrix cumulativeSumi() {
+ float s = 0.0f;
+ for (int i = 0; i < length; i++) {
+ s += get(i);
+ put(i, s);
+ }
+ return this;
+ }
+
+ /**
+ * Computes the cumulative sum, that is, the sum of all elements
+ * of the matrix up to a given index in linear addressing.
+ */
+ public FloatMatrix cumulativeSum() {
+ return dup().cumulativeSumi();
+ }
+
+ /** The scalar product of this with other. */
+ public float dot(FloatMatrix other) {
+ return SimpleBlas.dot(this, other);
+ }
+
+ /**
+ * The Euclidean norm of the matrix as vector, also the Frobenius
+ * norm of the matrix.
+ */
+ public float norm2() {
+ return SimpleBlas.nrm2(this);
+ }
+
+ /**
+ * The maximum norm of the matrix (maximal absolute value of the elements).
+ */
+ public float normmax() {
+ int i = SimpleBlas.iamax(this);
+ return Math.abs(get(i));
+ }
+
+ /**
+ * The 1-norm of the matrix as vector (sum of absolute values of elements).
+ */
+ public float norm1() {
+ return SimpleBlas.asum(this);
+ }
+
+ /**
+ * Return a new matrix with all elements sorted.
+ */
+ public FloatMatrix sort() {
+ float array[] = toArray();
+ java.util.Arrays.sort(array);
+ return new FloatMatrix(rows, columns, array);
+ }
+
+ /**
+ * Sort elements in-place.
+ */
+ public FloatMatrix sorti() {
+ Arrays.sort(data);
+ return this;
+ }
+
+ /**
+ * Get the sorting permutation.
+ *
+ * @return an int[] array such that which indexes the elements in sorted
+ * order.
+ */
+ public int[] sortingPermutation() {
+ Integer[] indices = new Integer[length];
+
+ for (int i = 0; i < length; i++) {
+ indices[i] = i;
+ }
+
+ final float[] array = data;
+
+ Arrays.sort(indices, new Comparator() {
+
+ public int compare(Object o1, Object o2) {
+ int i = (Integer) o1;
+ int j = (Integer) o2;
+ if (array[i] < array[j]) {
+ return -1;
+ } else if (array[i] == array[j]) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ });
+
+ int[] result = new int[length];
+
+ for (int i = 0; i < length; i++) {
+ result[i] = indices[i];
+ }
+
+ return result;
+ }
+
+ /**
+ * Sort columns (in-place).
+ */
+ public FloatMatrix sortColumnsi() {
+ for (int i = 0; i < length; i += rows) {
+ Arrays.sort(data, i, i + rows);
+ }
+ return this;
+ }
+
+ /** Sort columns. */
+ public FloatMatrix sortColumns() {
+ return dup().sortColumnsi();
+ }
+
+ /** Return matrix of indices which sort all columns. */
+ public int[][] columnSortingPermutations() {
+ int[][] result = new int[columns][];
+
+ FloatMatrix temp = new FloatMatrix(rows);
+ for (int c = 0; c < columns; c++) {
+ result[c] = getColumn(c, temp).sortingPermutation();
+ }
+
+ return result;
+ }
+
+ /** Sort rows (in-place). */
+ public FloatMatrix sortRowsi() {
+ // actually, this is much harder because the data is not consecutive
+ // in memory...
+ FloatMatrix temp = new FloatMatrix(columns);
+ for (int r = 0; r < rows; r++) {
+ putRow(r, getRow(r, temp).sorti());
+ }
+ return this;
+ }
+
+ /** Sort rows. */
+ public FloatMatrix sortRows() {
+ return dup().sortRowsi();
+ }
+
+ /** Return matrix of indices which sort all columns. */
+ public int[][] rowSortingPermutations() {
+ int[][] result = new int[rows][];
+
+ FloatMatrix temp = new FloatMatrix(columns);
+ for (int r = 0; r < rows; r++) {
+ result[r] = getRow(r, temp).sortingPermutation();
+ }
+
+ return result;
+ }
+
+ /** Return a vector containing the sums of the columns (having number of columns many entries) */
+ public FloatMatrix columnSums() {
+ if (rows == 1) {
+ return dup();
+ } else {
+ FloatMatrix v = new FloatMatrix(1, columns);
+
+ for (int c = 0; c < columns; c++) {
+ for (int r = 0; r < rows; r++) {
+ v.put(c, v.get(c) + get(r, c));
+ }
+ }
+
+ return v;
+ }
+ }
+
+ /** Return a vector containing the means of all columns. */
+ public FloatMatrix columnMeans() {
+ return columnSums().divi(rows);
+ }
+
+ /** Return a vector containing the sum of the rows. */
+ public FloatMatrix rowSums() {
+ if (columns == 1) {
+ return dup();
+ } else {
+ FloatMatrix v = new FloatMatrix(rows);
+
+ for (int c = 0; c < columns; c++) {
+ for (int r = 0; r < rows; r++) {
+ v.put(r, v.get(r) + get(r, c));
+ }
+ }
+
+ return v;
+ }
+ }
+
+ /** Return a vector containing the means of the rows. */
+ public FloatMatrix rowMeans() {
+ return rowSums().divi(columns);
+ }
+
+ /** Get a copy of a column. */
+ public FloatMatrix getColumn(int c) {
+ return getColumn(c, new FloatMatrix(rows, 1));
+ }
+
+ /** Copy a column to the given vector. */
+ public FloatMatrix getColumn(int c, FloatMatrix result) {
+ result.checkLength(rows);
+ JavaBlas.rcopy(rows, data, index(0, c), 1, result.data, 0, 1);
+ return result;
+ }
+
+ /** Copy a column back into the matrix. */
+ public void putColumn(int c, FloatMatrix v) {
+ JavaBlas.rcopy(rows, v.data, 0, 1, data, index(0, c), 1);
+ }
+
+ /** Get a copy of a row. */
+ public FloatMatrix getRow(int r) {
+ return getRow(r, new FloatMatrix(1, columns));
+ }
+
+ /** Copy a row to a given vector. */
+ public FloatMatrix getRow(int r, FloatMatrix result) {
+ result.checkLength(columns);
+ JavaBlas.rcopy(columns, data, index(r, 0), rows, result.data, 0, 1);
+ return result;
+ }
+
+ /** Copy a row back into the matrix. */
+ public void putRow(int r, FloatMatrix v) {
+ JavaBlas.rcopy(columns, v.data, 0, 1, data, index(r, 0), rows);
+ }
+
+ /** Return column-wise minimums. */
+ public FloatMatrix columnMins() {
+ FloatMatrix mins = new FloatMatrix(1, columns);
+ for (int c = 0; c < columns; c++) {
+ mins.put(c, getColumn(c).min());
+ }
+ return mins;
+ }
+
+ /** Return index of minimal element per column. */
+ public int[] columnArgmins() {
+ int[] argmins = new int[columns];
+ for (int c = 0; c < columns; c++) {
+ argmins[c] = getColumn(c).argmin();
+ }
+ return argmins;
+ }
+
+ /** Return column-wise maximums. */
+ public FloatMatrix columnMaxs() {
+ FloatMatrix maxs = new FloatMatrix(1, columns);
+ for (int c = 0; c < columns; c++) {
+ maxs.put(c, getColumn(c).max());
+ }
+ return maxs;
+ }
+
+ /** Return index of minimal element per column. */
+ public int[] columnArgmaxs() {
+ int[] argmaxs = new int[columns];
+ for (int c = 0; c < columns; c++) {
+ argmaxs[c] = getColumn(c).argmax();
+ }
+ return argmaxs;
+ }
+
+ /** Return row-wise minimums. */
+ public FloatMatrix rowMins() {
+ FloatMatrix mins = new FloatMatrix(rows);
+ for (int c = 0; c < rows; c++) {
+ mins.put(c, getRow(c).min());
+ }
+ return mins;
+ }
+
+ /** Return index of minimal element per row. */
+ public int[] rowArgmins() {
+ int[] argmins = new int[rows];
+ for (int c = 0; c < rows; c++) {
+ argmins[c] = getRow(c).argmin();
+ }
+ return argmins;
+ }
+
+ /** Return row-wise maximums. */
+ public FloatMatrix rowMaxs() {
+ FloatMatrix maxs = new FloatMatrix(rows);
+ for (int c = 0; c < rows; c++) {
+ maxs.put(c, getRow(c).max());
+ }
+ return maxs;
+ }
+
+ /** Return index of minimal element per row. */
+ public int[] rowArgmaxs() {
+ int[] argmaxs = new int[rows];
+ for (int c = 0; c < rows; c++) {
+ argmaxs[c] = getRow(c).argmax();
+ }
+ return argmaxs;
+ }
+
+ /**************************************************************************
+ * Elementwise Functions
+ */
+ /** Add a row vector to all rows of the matrix (in place). */
+ public FloatMatrix addiRowVector(FloatMatrix x) {
+ x.checkLength(columns);
+ for (int r = 0; r < rows; r++) {
+ JavaBlas.raxpy(columns, 1.0f, x.data, 0, 1, data, index(r, 0), rows);
+ }
+ return this;
+ }
+
+ /** Add a row to all rows of the matrix. */
+ public FloatMatrix addRowVector(FloatMatrix x) {
+ return dup().addiRowVector(x);
+ }
+
+ /** Add a vector to all columns of the matrix (in-place). */
+ public FloatMatrix addiColumnVector(FloatMatrix x) {
+ x.checkLength(rows);
+ for (int c = 0; c < columns; c++) {
+ JavaBlas.raxpy(rows, 1.0f, x.data, 0, 1, data, index(0, c), 1);
+ }
+ return this;
+ }
+
+ /** Add a vector to all columns of the matrix. */
+ public FloatMatrix addColumnVector(FloatMatrix x) {
+ return dup().addiColumnVector(x);
+ }
+
+ /** Subtract a row vector from all rows of the matrix (in-place). */
+ public FloatMatrix subiRowVector(FloatMatrix x) {
+ // This is a bit crazy, but a row vector must have as length as the columns of the matrix.
+ x.checkLength(columns);
+ for (int r = 0; r < rows; r++) {
+ JavaBlas.raxpy(columns, -1.0f, x.data, 0, 1, data, index(r, 0), rows);
+ }
+ return this;
+ }
+
+ /** Subtract a row vector from all rows of the matrix. */
+ public FloatMatrix subRowVector(FloatMatrix x) {
+ return dup().subiRowVector(x);
+ }
+
+ /** Subtract a column vector from all columns of the matrix (in-place). */
+ public FloatMatrix subiColumnVector(FloatMatrix x) {
+ x.checkLength(rows);
+ for (int c = 0; c < columns; c++) {
+ JavaBlas.raxpy(rows, -1.0f, x.data, 0, 1, data, index(0, c), 1);
+ }
+ return this;
+ }
+
+ /** Subtract a vector from all columns of the matrix. */
+ public FloatMatrix subColumnVector(FloatMatrix x) {
+ return dup().subiColumnVector(x);
+ }
+
+ /** Multiply a row by a scalar. */
+ public FloatMatrix mulRow(int r, float scale) {
+ Blas.sscal(columns, scale, data, index(r, 0), rows);
+ return this;
+ }
+
+ /** Multiply a column by a scalar. */
+ public FloatMatrix mulColumn(int c, float scale) {
+ Blas.sscal(rows, scale, data, index(0, c), 1);
+ return this;
+ }
+
+ /** Multiply all columns with a column vector (in-place). */
+ public FloatMatrix muliColumnVector(FloatMatrix x) {
+ x.checkLength(rows);
+ for (int c = 0; c < columns; c++) {
+ for (int r = 0; r < rows; r++)
+ put(r, c, get(r, c) * x.get(r));
+ }
+ return this;
+ }
+
+ /** Multiply all columns with a column vector. */
+ public FloatMatrix mulColumnVector(FloatMatrix x) {
+ return dup().muliColumnVector(x);
+ }
+
+ /** Multiply all rows with a row vector (in-place). */
+ public FloatMatrix muliRowVector(FloatMatrix x) {
+ x.checkLength(columns);
+ for (int c = 0; c < columns; c++)
+ for (int r = 0; r < rows; r++)
+ put(r, c, get(r, c) * x.get(c));
+ return this;
+ }
+
+ /** Multiply all rows with a row vector. */
+ public FloatMatrix mulRowVector(FloatMatrix x) {
+ return dup().muliRowVector(x);
+ }
+
+ /**
+ * Writes out this matrix to the given data stream.
+ * @param dos the data output stream to write to.
+ * @throws IOException
+ */
+ public void out(DataOutputStream dos) throws IOException {
+ dos.writeUTF("float");
+ dos.writeInt(columns);
+ dos.writeInt(rows);
+
+ dos.writeInt(data.length);
+ for (int i = 0; i < data.length; i++) {
+ dos.writeDouble(data[i]);
+ }
+ }
+
+ /**
+ * Reads in a matrix from the given data stream. Note
+ * that the old data of this matrix will be discarded.
+ * @param dis the data input stream to read from.
+ * @throws IOException
+ */
+ public void in(DataInputStream dis) throws IOException {
+ if (!dis.readUTF().equals("float")) {
+ throw new IllegalStateException("The matrix in the specified file is not of the correct type!");
+ }
+
+ this.columns = dis.readInt();
+ this.rows = dis.readInt();
+
+ final int MAX = dis.readInt();
+ data = new float[MAX];
+ for (int i = 0; i < MAX; i++) {
+ data[i] = dis.readFloat();
+ }
+ }
+
+ /**
+ * Saves this matrix to the specified file.
+ * @param filename the file to write the matrix in.
+ * @throws IOException thrown on errors while writing the matrix to the file
+ */
+ public void save(String filename) throws IOException {
+ DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename, false));
+ this.out(dos);
+ }
+
+ /**
+ * Loads a matrix from a file into this matrix. Note that the old data
+ * of this matrix will be discarded.
+ * @param filename the file to read the matrix from
+ * @throws IOException thrown on errors while reading the matrix
+ */
+ public void load(String filename) throws IOException {
+ DataInputStream dis = new DataInputStream(new FileInputStream(filename));
+ this.in(dis);
+ }
+
+ public static FloatMatrix loadAsciiFile(String filename) throws IOException {
+ BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+
+ // Go through file and count columns and rows. What makes this endeavour a bit difficult is
+ // that files can have leading or trailing spaces leading to spurious fields
+ // after String.split().
+ String line;
+ int rows = 0;
+ int columns = -1;
+ while ((line = is.readLine()) != null) {
+ String[] elements = line.split("\\s+");
+ int numElements = elements.length;
+ if (elements[0].length() == 0) {
+ numElements--;
+ }
+ if (elements[elements.length - 1].length() == 0) {
+ numElements--;
+ }
+
+ if (columns == -1) {
+ columns = numElements;
+ } else {
+ if (columns != numElements) {
+ throw new IOException("Number of elements changes in line " + line + ".");
+ }
+ }
+
+ rows++;
+ }
+ is.close();
+
+ // Go through file a second time process the actual data.
+ is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+ FloatMatrix result = new FloatMatrix(rows, columns);
+ int r = 0;
+ while ((line = is.readLine()) != null) {
+ String[] elements = line.split("\\s+");
+ int firstElement = (elements[0].length() == 0) ? 1 : 0;
+ for (int c = 0, cc = firstElement; c < columns; c++, cc++) {
+ result.put(r, c, Float.valueOf(elements[cc]));
+ }
+ r++;
+ }
+ return result;
+ }
+
+ /****************************************************************
+ * Autogenerated code
+ */
+ /***** Code for operators ***************************************/
+
+ /* Overloads for the usual arithmetic operations */
+ /*#
+ def gen_overloads(base, result_rows, result_cols, verb=''); <<-EOS
+ #{doc verb.capitalize + " a matrix (in place)."}
+ public FloatMatrix #{base}i(FloatMatrix other) {
+ return #{base}i(other, this);
+ }
+
+ #{doc verb.capitalize + " a matrix (in place)."}
+ public FloatMatrix #{base}(FloatMatrix other) {
+ return #{base}i(other, new FloatMatrix(#{result_rows}, #{result_cols}));
+ }
+
+ #{doc verb.capitalize + " a scalar (in place)."}
+ public FloatMatrix #{base}i(float v) {
+ return #{base}i(v, this);
+ }
+
+ #{doc verb.capitalize + " a scalar."}
+ public FloatMatrix #{base}(float v) {
+ return #{base}i(v, new FloatMatrix(rows, columns));
+ }
+ EOS
+ end
+ #*/
+
+ /* Generating code for logical operators. This not only generates the stubs
+ * but really all of the code.
+ */
+ /*#
+ def gen_compare(name, op, cmp); <<-EOS
+ #{doc 'Test for ' + cmp + ' (in-place).'}
+ public FloatMatrix #{name}i(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar())
+ return #{name}i(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) #{op} other.get(i) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ #{doc 'Test for ' + cmp + ' (in-place).'}
+ public FloatMatrix #{name}i(FloatMatrix other) {
+ return #{name}i(other, this);
+ }
+
+ #{doc 'Test for ' + cmp + '.'}
+ public FloatMatrix #{name}(FloatMatrix other) {
+ return #{name}i(other, new FloatMatrix(rows, columns));
+ }
+
+ #{doc 'Test for ' + cmp + ' against a scalar (in-place).'}
+ public FloatMatrix #{name}i(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) #{op} value ? 1.0f : 0.0f);
+ return result;
+ }
+
+ #{doc 'Test for ' + cmp + ' against a scalar (in-place).'}
+ public FloatMatrix #{name}i(float value) {
+ return #{name}i(value, this);
+ }
+
+ #{doc 'test for ' + cmp + ' against a scalar.'}
+ public FloatMatrix #{name}(float value) {
+ return #{name}i(value, new FloatMatrix(rows, columns));
+ }
+ EOS
+ end
+ #*/
+ /*#
+ def gen_logical(name, op, cmp); <<-EOS
+ #{doc 'Compute elementwise ' + cmp + ' (in-place).'}
+ public FloatMatrix #{name}i(FloatMatrix other, FloatMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0f) #{op} (other.get(i) != 0.0f) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ #{doc 'Compute elementwise ' + cmp + ' (in-place).'}
+ public FloatMatrix #{name}i(FloatMatrix other) {
+ return #{name}i(other, this);
+ }
+
+ #{doc 'Compute elementwise ' + cmp + '.'}
+ public FloatMatrix #{name}(FloatMatrix other) {
+ return #{name}i(other, new FloatMatrix(rows, columns));
+ }
+
+ #{doc 'Compute elementwise ' + cmp + ' against a scalar (in-place).'}
+ public FloatMatrix #{name}i(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = (value != 0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0f) #{op} val ? 1.0f : 0.0f);
+ return result;
+ }
+
+ #{doc 'Compute elementwise ' + cmp + ' against a scalar (in-place).'}
+ public FloatMatrix #{name}i(float value) {
+ return #{name}i(value, this);
+ }
+
+ #{doc 'Compute elementwise ' + cmp + ' against a scalar.'}
+ public FloatMatrix #{name}(float value) {
+ return #{name}i(value, new FloatMatrix(rows, columns));
+ }
+ EOS
+ end
+ #*/
+
+ /*# collect(gen_overloads('add', 'rows', 'columns', 'add'),
+ gen_overloads('sub', 'rows', 'columns', 'subtract'),
+ gen_overloads('rsub', 'rows', 'columns', '(right-)subtract'),
+ gen_overloads('div', 'rows', 'columns', 'elementwise divide by'),
+ gen_overloads('rdiv', 'rows', 'columns', '(right-)elementwise divide by'),
+ gen_overloads('mul', 'rows', 'columns', 'elementwise multiply by'),
+ gen_overloads('mmul', 'rows', 'other.columns', 'matrix-multiply by'),
+ gen_compare('lt', '<', '"less than"'),
+ gen_compare('gt', '>', '"greater than"'),
+ gen_compare('le', '<=', '"less than or equal"'),
+ gen_compare('ge', '>=', '"greater than or equal"'),
+ gen_compare('eq', '==', 'equality'),
+ gen_compare('ne', '!=', 'inequality'),
+ gen_logical('and', '&', 'logical and'),
+ gen_logical('or', '|', 'logical or'),
+ gen_logical('xor', '^', 'logical xor'))
+ #*/
+//RJPP-BEGIN------------------------------------------------------------
+ /** Add a matrix (in place). */
+ public FloatMatrix addi(FloatMatrix other) {
+ return addi(other, this);
+ }
+
+ /** Add a matrix (in place). */
+ public FloatMatrix add(FloatMatrix other) {
+ return addi(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Add a scalar (in place). */
+ public FloatMatrix addi(float v) {
+ return addi(v, this);
+ }
+
+ /** Add a scalar. */
+ public FloatMatrix add(float v) {
+ return addi(v, new FloatMatrix(rows, columns));
+ }
+
+ /** Subtract a matrix (in place). */
+ public FloatMatrix subi(FloatMatrix other) {
+ return subi(other, this);
+ }
+
+ /** Subtract a matrix (in place). */
+ public FloatMatrix sub(FloatMatrix other) {
+ return subi(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Subtract a scalar (in place). */
+ public FloatMatrix subi(float v) {
+ return subi(v, this);
+ }
+
+ /** Subtract a scalar. */
+ public FloatMatrix sub(float v) {
+ return subi(v, new FloatMatrix(rows, columns));
+ }
+
+ /** (right-)subtract a matrix (in place). */
+ public FloatMatrix rsubi(FloatMatrix other) {
+ return rsubi(other, this);
+ }
+
+ /** (right-)subtract a matrix (in place). */
+ public FloatMatrix rsub(FloatMatrix other) {
+ return rsubi(other, new FloatMatrix(rows, columns));
+ }
+
+ /** (right-)subtract a scalar (in place). */
+ public FloatMatrix rsubi(float v) {
+ return rsubi(v, this);
+ }
+
+ /** (right-)subtract a scalar. */
+ public FloatMatrix rsub(float v) {
+ return rsubi(v, new FloatMatrix(rows, columns));
+ }
+
+ /** Elementwise divide by a matrix (in place). */
+ public FloatMatrix divi(FloatMatrix other) {
+ return divi(other, this);
+ }
+
+ /** Elementwise divide by a matrix (in place). */
+ public FloatMatrix div(FloatMatrix other) {
+ return divi(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Elementwise divide by a scalar (in place). */
+ public FloatMatrix divi(float v) {
+ return divi(v, this);
+ }
+
+ /** Elementwise divide by a scalar. */
+ public FloatMatrix div(float v) {
+ return divi(v, new FloatMatrix(rows, columns));
+ }
+
+ /** (right-)elementwise divide by a matrix (in place). */
+ public FloatMatrix rdivi(FloatMatrix other) {
+ return rdivi(other, this);
+ }
+
+ /** (right-)elementwise divide by a matrix (in place). */
+ public FloatMatrix rdiv(FloatMatrix other) {
+ return rdivi(other, new FloatMatrix(rows, columns));
+ }
+
+ /** (right-)elementwise divide by a scalar (in place). */
+ public FloatMatrix rdivi(float v) {
+ return rdivi(v, this);
+ }
+
+ /** (right-)elementwise divide by a scalar. */
+ public FloatMatrix rdiv(float v) {
+ return rdivi(v, new FloatMatrix(rows, columns));
+ }
+
+ /** Elementwise multiply by a matrix (in place). */
+ public FloatMatrix muli(FloatMatrix other) {
+ return muli(other, this);
+ }
+
+ /** Elementwise multiply by a matrix (in place). */
+ public FloatMatrix mul(FloatMatrix other) {
+ return muli(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Elementwise multiply by a scalar (in place). */
+ public FloatMatrix muli(float v) {
+ return muli(v, this);
+ }
+
+ /** Elementwise multiply by a scalar. */
+ public FloatMatrix mul(float v) {
+ return muli(v, new FloatMatrix(rows, columns));
+ }
+
+ /** Matrix-multiply by a matrix (in place). */
+ public FloatMatrix mmuli(FloatMatrix other) {
+ return mmuli(other, this);
+ }
+
+ /** Matrix-multiply by a matrix (in place). */
+ public FloatMatrix mmul(FloatMatrix other) {
+ return mmuli(other, new FloatMatrix(rows, other.columns));
+ }
+
+ /** Matrix-multiply by a scalar (in place). */
+ public FloatMatrix mmuli(float v) {
+ return mmuli(v, this);
+ }
+
+ /** Matrix-multiply by a scalar. */
+ public FloatMatrix mmul(float v) {
+ return mmuli(v, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for "less than" (in-place). */
+ public FloatMatrix lti(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar())
+ return lti(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) < other.get(i) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for "less than" (in-place). */
+ public FloatMatrix lti(FloatMatrix other) {
+ return lti(other, this);
+ }
+
+ /** Test for "less than". */
+ public FloatMatrix lt(FloatMatrix other) {
+ return lti(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for "less than" against a scalar (in-place). */
+ public FloatMatrix lti(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) < value ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for "less than" against a scalar (in-place). */
+ public FloatMatrix lti(float value) {
+ return lti(value, this);
+ }
+
+ /** test for "less than" against a scalar. */
+ public FloatMatrix lt(float value) {
+ return lti(value, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for "greater than" (in-place). */
+ public FloatMatrix gti(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar())
+ return gti(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) > other.get(i) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for "greater than" (in-place). */
+ public FloatMatrix gti(FloatMatrix other) {
+ return gti(other, this);
+ }
+
+ /** Test for "greater than". */
+ public FloatMatrix gt(FloatMatrix other) {
+ return gti(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for "greater than" against a scalar (in-place). */
+ public FloatMatrix gti(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) > value ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for "greater than" against a scalar (in-place). */
+ public FloatMatrix gti(float value) {
+ return gti(value, this);
+ }
+
+ /** test for "greater than" against a scalar. */
+ public FloatMatrix gt(float value) {
+ return gti(value, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for "less than or equal" (in-place). */
+ public FloatMatrix lei(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar())
+ return lei(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) <= other.get(i) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for "less than or equal" (in-place). */
+ public FloatMatrix lei(FloatMatrix other) {
+ return lei(other, this);
+ }
+
+ /** Test for "less than or equal". */
+ public FloatMatrix le(FloatMatrix other) {
+ return lei(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for "less than or equal" against a scalar (in-place). */
+ public FloatMatrix lei(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) <= value ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for "less than or equal" against a scalar (in-place). */
+ public FloatMatrix lei(float value) {
+ return lei(value, this);
+ }
+
+ /** test for "less than or equal" against a scalar. */
+ public FloatMatrix le(float value) {
+ return lei(value, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for "greater than or equal" (in-place). */
+ public FloatMatrix gei(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar())
+ return gei(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) >= other.get(i) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for "greater than or equal" (in-place). */
+ public FloatMatrix gei(FloatMatrix other) {
+ return gei(other, this);
+ }
+
+ /** Test for "greater than or equal". */
+ public FloatMatrix ge(FloatMatrix other) {
+ return gei(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for "greater than or equal" against a scalar (in-place). */
+ public FloatMatrix gei(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) >= value ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for "greater than or equal" against a scalar (in-place). */
+ public FloatMatrix gei(float value) {
+ return gei(value, this);
+ }
+
+ /** test for "greater than or equal" against a scalar. */
+ public FloatMatrix ge(float value) {
+ return gei(value, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for equality (in-place). */
+ public FloatMatrix eqi(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar())
+ return eqi(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) == other.get(i) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for equality (in-place). */
+ public FloatMatrix eqi(FloatMatrix other) {
+ return eqi(other, this);
+ }
+
+ /** Test for equality. */
+ public FloatMatrix eq(FloatMatrix other) {
+ return eqi(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for equality against a scalar (in-place). */
+ public FloatMatrix eqi(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) == value ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for equality against a scalar (in-place). */
+ public FloatMatrix eqi(float value) {
+ return eqi(value, this);
+ }
+
+ /** test for equality against a scalar. */
+ public FloatMatrix eq(float value) {
+ return eqi(value, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for inequality (in-place). */
+ public FloatMatrix nei(FloatMatrix other, FloatMatrix result) {
+ if (other.isScalar())
+ return nei(other.scalar(), result);
+
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) != other.get(i) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for inequality (in-place). */
+ public FloatMatrix nei(FloatMatrix other) {
+ return nei(other, this);
+ }
+
+ /** Test for inequality. */
+ public FloatMatrix ne(FloatMatrix other) {
+ return nei(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Test for inequality against a scalar (in-place). */
+ public FloatMatrix nei(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ for (int i = 0; i < length; i++)
+ result.put(i, get(i) != value ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Test for inequality against a scalar (in-place). */
+ public FloatMatrix nei(float value) {
+ return nei(value, this);
+ }
+
+ /** test for inequality against a scalar. */
+ public FloatMatrix ne(float value) {
+ return nei(value, new FloatMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical and (in-place). */
+ public FloatMatrix andi(FloatMatrix other, FloatMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0f) & (other.get(i) != 0.0f) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Compute elementwise logical and (in-place). */
+ public FloatMatrix andi(FloatMatrix other) {
+ return andi(other, this);
+ }
+
+ /** Compute elementwise logical and. */
+ public FloatMatrix and(FloatMatrix other) {
+ return andi(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical and against a scalar (in-place). */
+ public FloatMatrix andi(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = (value != 0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0f) & val ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Compute elementwise logical and against a scalar (in-place). */
+ public FloatMatrix andi(float value) {
+ return andi(value, this);
+ }
+
+ /** Compute elementwise logical and against a scalar. */
+ public FloatMatrix and(float value) {
+ return andi(value, new FloatMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical or (in-place). */
+ public FloatMatrix ori(FloatMatrix other, FloatMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0f) | (other.get(i) != 0.0f) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Compute elementwise logical or (in-place). */
+ public FloatMatrix ori(FloatMatrix other) {
+ return ori(other, this);
+ }
+
+ /** Compute elementwise logical or. */
+ public FloatMatrix or(FloatMatrix other) {
+ return ori(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical or against a scalar (in-place). */
+ public FloatMatrix ori(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = (value != 0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0f) | val ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Compute elementwise logical or against a scalar (in-place). */
+ public FloatMatrix ori(float value) {
+ return ori(value, this);
+ }
+
+ /** Compute elementwise logical or against a scalar. */
+ public FloatMatrix or(float value) {
+ return ori(value, new FloatMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical xor (in-place). */
+ public FloatMatrix xori(FloatMatrix other, FloatMatrix result) {
+ assertSameLength(other);
+ ensureResultLength(other, result);
+
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0f) ^ (other.get(i) != 0.0f) ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Compute elementwise logical xor (in-place). */
+ public FloatMatrix xori(FloatMatrix other) {
+ return xori(other, this);
+ }
+
+ /** Compute elementwise logical xor. */
+ public FloatMatrix xor(FloatMatrix other) {
+ return xori(other, new FloatMatrix(rows, columns));
+ }
+
+ /** Compute elementwise logical xor against a scalar (in-place). */
+ public FloatMatrix xori(float value, FloatMatrix result) {
+ ensureResultLength(null, result);
+ boolean val = (value != 0.0f);
+ for (int i = 0; i < length; i++)
+ result.put(i, (get(i) != 0.0f) ^ val ? 1.0f : 0.0f);
+ return result;
+ }
+
+ /** Compute elementwise logical xor against a scalar (in-place). */
+ public FloatMatrix xori(float value) {
+ return xori(value, this);
+ }
+
+ /** Compute elementwise logical xor against a scalar. */
+ public FloatMatrix xor(float value) {
+ return xori(value, new FloatMatrix(rows, columns));
+ }
+//RJPP-END--------------------------------------------------------------
+}
diff --git a/src/org/jblas/la/Geometry.java b/src/org/jblas/la/Geometry.java
new file mode 100644
index 0000000..89186df
--- /dev/null
+++ b/src/org/jblas/la/Geometry.java
@@ -0,0 +1,181 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+/**
+ * <p>General functions which are geometric in nature.</p>
+ *
+ * <p>For example, computing all pairwise squared distances between all columns of a matrix.</p>
+ */
+public class Geometry {
+
+ /**
+ * <p>Compute the pairwise squared distances between all columns of the two
+ * matrices.</p>
+ *
+ * <p>An efficient way to do this is to observe that <i>(x-y)^2 = x^2 - 2xy - y^2</i>
+ * and to then properly carry out the computation with matrices.</p>
+ */
+ public static DoubleMatrix pairwiseSquaredDistances(DoubleMatrix X, DoubleMatrix Y) {
+ if (X.rows != Y.rows)
+ throw new IllegalArgumentException(
+ "Matrices must have same number of rows");
+
+ DoubleMatrix XX = X.mul(X).columnSums();
+ DoubleMatrix YY = Y.mul(Y).columnSums();
+
+ DoubleMatrix Z = X.transpose().mmul(Y);
+ Z.muli(-2.0); //Z.print();
+ Z.addiColumnVector(XX);
+ Z.addiRowVector(YY);
+
+ return Z;
+ }
+
+ /** Center a vector (subtract mean from all elements (in-place). */
+ public static DoubleMatrix center(DoubleMatrix x) {
+ return x.subi(x.mean());
+ }
+
+ /** Center the rows of a matrix (in-place). */
+ public static DoubleMatrix centerRows(DoubleMatrix x) {
+ DoubleMatrix temp = new DoubleMatrix(x.columns);
+ for (int r = 0; r < x.rows; r++)
+ x.putRow(r, center(x.getRow(r, temp)));
+ return x;
+ }
+
+ /** Center the columns of a matrix (in-place). */
+ public static DoubleMatrix centerColumns(DoubleMatrix x) {
+ DoubleMatrix temp = new DoubleMatrix(x.rows);
+ for (int c = 0; c < x.columns; c++)
+ x.putColumn(c, center(x.getColumn(c, temp)));
+ return x;
+ }
+
+ /** Normalize a vector (scale such that its Euclidean norm is 1) (in-place). */
+ public static DoubleMatrix normalize(DoubleMatrix x) {
+ return x.divi(x.norm2());
+ }
+
+ /** Normalize the rows of a matrix (in-place). */
+ public static DoubleMatrix normalizeRows(DoubleMatrix x) {
+ DoubleMatrix temp = new DoubleMatrix(x.columns);
+ for (int r = 0; r < x.rows; r++)
+ x.putRow(r, normalize(x.getRow(r, temp)));
+ return x;
+ }
+
+ /** Normalize the columns of a matrix (in-place). */
+ public static DoubleMatrix normalizeColumns(DoubleMatrix x) {
+ DoubleMatrix temp = new DoubleMatrix(x.rows);
+ for (int c = 0; c < x.columns; c++)
+ x.putColumn(c, normalize(x.getColumn(c, temp)));
+ return x;
+ }
+
+//BEGIN
+ // The code below has been automatically generated.
+ // DO NOT EDIT!
+
+ /**
+ * <p>Compute the pairwise squared distances between all columns of the two
+ * matrices.</p>
+ *
+ * <p>An efficient way to do this is to observe that <i>(x-y)^2 = x^2 - 2xy - y^2</i>
+ * and to then properly carry out the computation with matrices.</p>
+ */
+ public static FloatMatrix pairwiseSquaredDistances(FloatMatrix X, FloatMatrix Y) {
+ if (X.rows != Y.rows)
+ throw new IllegalArgumentException(
+ "Matrices must have same number of rows");
+
+ FloatMatrix XX = X.mul(X).columnSums();
+ FloatMatrix YY = Y.mul(Y).columnSums();
+
+ FloatMatrix Z = X.transpose().mmul(Y);
+ Z.muli(-2.0f); //Z.print();
+ Z.addiColumnVector(XX);
+ Z.addiRowVector(YY);
+
+ return Z;
+ }
+
+ /** Center a vector (subtract mean from all elements (in-place). */
+ public static FloatMatrix center(FloatMatrix x) {
+ return x.subi(x.mean());
+ }
+
+ /** Center the rows of a matrix (in-place). */
+ public static FloatMatrix centerRows(FloatMatrix x) {
+ FloatMatrix temp = new FloatMatrix(x.columns);
+ for (int r = 0; r < x.rows; r++)
+ x.putRow(r, center(x.getRow(r, temp)));
+ return x;
+ }
+
+ /** Center the columns of a matrix (in-place). */
+ public static FloatMatrix centerColumns(FloatMatrix x) {
+ FloatMatrix temp = new FloatMatrix(x.rows);
+ for (int c = 0; c < x.columns; c++)
+ x.putColumn(c, center(x.getColumn(c, temp)));
+ return x;
+ }
+
+ /** Normalize a vector (scale such that its Euclidean norm is 1) (in-place). */
+ public static FloatMatrix normalize(FloatMatrix x) {
+ return x.divi(x.norm2());
+ }
+
+ /** Normalize the rows of a matrix (in-place). */
+ public static FloatMatrix normalizeRows(FloatMatrix x) {
+ FloatMatrix temp = new FloatMatrix(x.columns);
+ for (int r = 0; r < x.rows; r++)
+ x.putRow(r, normalize(x.getRow(r, temp)));
+ return x;
+ }
+
+ /** Normalize the columns of a matrix (in-place). */
+ public static FloatMatrix normalizeColumns(FloatMatrix x) {
+ FloatMatrix temp = new FloatMatrix(x.rows);
+ for (int c = 0; c < x.columns; c++)
+ x.putColumn(c, normalize(x.getColumn(c, temp)));
+ return x;
+ }
+
+//END
+}
diff --git a/src/org/jblas/la/JavaBlas.java b/src/org/jblas/la/JavaBlas.java
new file mode 100644
index 0000000..f6184d8
--- /dev/null
+++ b/src/org/jblas/la/JavaBlas.java
@@ -0,0 +1,286 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.jblas.la;
+
+import org.jblas.la.exceptions.LapackException;
+
+/**
+ * <p>Implementation of some Blas functions, mostly those which require linear runtime
+ * in the number of matrix elements. Because of the copying overhead when passing
+ * primitive arrays to native code, it doesn't make sense for these functions
+ * to be implemented in native code. The Java code is about as fast.</p>
+ *
+ * <p>The same conventions were used as in the native code, that is, for each array
+ * you also pass an index pointing to the starting index.</p>
+ *
+ * <p>These methods are mostly optimized for the case where the starting index is 0
+ * and the increment is 1.</p>
+ */
+public class JavaBlas {
+
+ /** Exchange two vectors. */
+ public static void rswap(int n, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy) {
+ if (incx == 1 && incy == 1 && dxIdx == 0 && dyIdx == 0) {
+ double z;
+ for (int i = 0; i < n; i++) {
+ z = dx[i];
+ dx[i] = dy[i];
+ dy[i] = z;
+ }
+ } else {
+ double z;
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; xi += incx, yi += incy, c++) {
+ z = dx[xi];
+ dx[xi] = dy[yi];
+ dy[yi] = z;
+ }
+ }
+ }
+
+ /** Copy dx to dy. */
+ public static void rcopy(int n, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy) {
+ if (dxIdx < 0 || dxIdx + (n - 1) * incx >= dx.length) {
+ throw new LapackException("Java.raxpy", "Parameters for x aren't valid! (n = " + n + ", dx.length = " + dx.length + ", dxIdx = " + dxIdx + ", incx = " + incx + ")");
+ }
+ if (dyIdx < 0 || dyIdx + (n - 1) * incy >= dy.length) {
+ throw new LapackException("Java.raxpy", "Parameters for y aren't valid! (n = " + n + ", dy.length = " + dy.length + ", dyIdx = " + dyIdx + ", incy = " + incy + ")");
+ }
+ if (incx == 1 && incy == 1) {
+ System.arraycopy(dx, dxIdx, dy, dyIdx, n);
+ } else {
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; xi += incx, yi += incy, c++) {
+ dy[yi] = dx[xi];
+ }
+ }
+ }
+
+ /** Compute dy <- da * dx + dy. */
+ public static void raxpy(int n, double da, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy) {
+ if (dxIdx < 0 || dxIdx + (n - 1) * incx >= dx.length) {
+ throw new LapackException("Java.raxpy", "Parameters for x aren't valid! (n = " + n + ", dx.length = " + dx.length + ", dxIdx = " + dxIdx + ", incx = " + incx + ")");
+ }
+ if (dyIdx < 0 || dyIdx + (n - 1) * incy >= dy.length) {
+ throw new LapackException("Java.raxpy", "Parameters for y aren't valid! (n = " + n + ", dy.length = " + dy.length + ", dyIdx = " + dyIdx + ", incy = " + incy + ")");
+ }
+
+ if (incx == 1 && incy == 1 && dxIdx == 0 && dyIdx == 0) {
+ if (da == 1.0) {
+ for (int i = 0; i < n; i++) {
+ dy[i] += dx[i];
+ }
+ } else {
+ for (int i = 0; i < n; i++) {
+ dy[i] += da * dx[i];
+ }
+ }
+ } else {
+ if (da == 1.0) {
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; c++, xi += incx, yi += incy) {
+ dy[yi] += dx[xi];
+ }
+
+ } else {
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; c++, xi += incx, yi += incy) {
+ dy[yi] += da * dx[xi];
+ }
+ }
+ }
+ }
+
+ /** Computes dz <- dx + dy */
+ public static void rzaxpy(int n, double[] dz, int dzIdx, int incz, double da, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy) {
+ if (dxIdx == 0 && incx == 1 && dyIdx == 0 && incy == 1 && dzIdx == 0 && incz == 1) {
+ if (da == 1.0) {
+ for (int c = 0; c < n; c++)
+ dz[c] = dx[c] + dy[c];
+ } else {
+ for (int c = 0; c < n; c++)
+ dz[c] = da*dx[c] + dy[c];
+ }
+ } else {
+ if (da == 1.0) {
+ for (int c = 0, xi = dxIdx, yi = dyIdx, zi = dzIdx; c < n; c++, xi += incx, yi += incy, zi += incz) {
+ dz[zi] = dx[xi] + dy[yi];
+ }
+ } else {
+ for (int c = 0, xi = dxIdx, yi = dyIdx, zi = dzIdx; c < n; c++, xi += incx, yi += incy, zi += incz) {
+ dz[zi] = da*dx[xi] + dy[yi];
+ }
+ }
+ }
+ }
+
+ public static void rzgxpy(int n, double[] dz, double[] dx, double[] dy) {
+ for (int c = 0; c < n; c++)
+ dz[c] = dx[c] + dy[c];
+ }
+
+ /** Compute scalar product between dx and dy. */
+ public static double rdot(int n, double[] dx, int dxIdx, int incx, double[] dy, int dyIdx, int incy) {
+ double s = 0.0;
+ if (incx == 1 && incy == 1 && dxIdx == 0 && dyIdx == 0) {
+ for (int i = 0; i < n; i++)
+ s += dx[i] * dy[i];
+ }
+ else {
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; c++, xi += incx, yi += incy) {
+ s += dx[xi] * dy[yi];
+ }
+ }
+ return s;
+ }
+//BEGIN
+ // The code below has been automatically generated.
+ // DO NOT EDIT!
+
+ /** Exchange two vectors. */
+ public static void rswap(int n, float[] dx, int dxIdx, int incx, float[] dy, int dyIdx, int incy) {
+ if (incx == 1 && incy == 1 && dxIdx == 0 && dyIdx == 0) {
+ float z;
+ for (int i = 0; i < n; i++) {
+ z = dx[i];
+ dx[i] = dy[i];
+ dy[i] = z;
+ }
+ } else {
+ float z;
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; xi += incx, yi += incy, c++) {
+ z = dx[xi];
+ dx[xi] = dy[yi];
+ dy[yi] = z;
+ }
+ }
+ }
+
+ /** Copy dx to dy. */
+ public static void rcopy(int n, float[] dx, int dxIdx, int incx, float[] dy, int dyIdx, int incy) {
+ if (dxIdx < 0 || dxIdx + (n - 1) * incx >= dx.length) {
+ throw new LapackException("Java.raxpy", "Parameters for x aren't valid! (n = " + n + ", dx.length = " + dx.length + ", dxIdx = " + dxIdx + ", incx = " + incx + ")");
+ }
+ if (dyIdx < 0 || dyIdx + (n - 1) * incy >= dy.length) {
+ throw new LapackException("Java.raxpy", "Parameters for y aren't valid! (n = " + n + ", dy.length = " + dy.length + ", dyIdx = " + dyIdx + ", incy = " + incy + ")");
+ }
+ if (incx == 1 && incy == 1) {
+ System.arraycopy(dx, dxIdx, dy, dyIdx, n);
+ } else {
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; xi += incx, yi += incy, c++) {
+ dy[yi] = dx[xi];
+ }
+ }
+ }
+
+ /** Compute dy <- da * dx + dy. */
+ public static void raxpy(int n, float da, float[] dx, int dxIdx, int incx, float[] dy, int dyIdx, int incy) {
+ if (dxIdx < 0 || dxIdx + (n - 1) * incx >= dx.length) {
+ throw new LapackException("Java.raxpy", "Parameters for x aren't valid! (n = " + n + ", dx.length = " + dx.length + ", dxIdx = " + dxIdx + ", incx = " + incx + ")");
+ }
+ if (dyIdx < 0 || dyIdx + (n - 1) * incy >= dy.length) {
+ throw new LapackException("Java.raxpy", "Parameters for y aren't valid! (n = " + n + ", dy.length = " + dy.length + ", dyIdx = " + dyIdx + ", incy = " + incy + ")");
+ }
+
+ if (incx == 1 && incy == 1 && dxIdx == 0 && dyIdx == 0) {
+ if (da == 1.0f) {
+ for (int i = 0; i < n; i++) {
+ dy[i] += dx[i];
+ }
+ } else {
+ for (int i = 0; i < n; i++) {
+ dy[i] += da * dx[i];
+ }
+ }
+ } else {
+ if (da == 1.0f) {
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; c++, xi += incx, yi += incy) {
+ dy[yi] += dx[xi];
+ }
+
+ } else {
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; c++, xi += incx, yi += incy) {
+ dy[yi] += da * dx[xi];
+ }
+ }
+ }
+ }
+
+ /** Computes dz <- dx + dy */
+ public static void rzaxpy(int n, float[] dz, int dzIdx, int incz, float da, float[] dx, int dxIdx, int incx, float[] dy, int dyIdx, int incy) {
+ if (dxIdx == 0 && incx == 1 && dyIdx == 0 && incy == 1 && dzIdx == 0 && incz == 1) {
+ if (da == 1.0f) {
+ for (int c = 0; c < n; c++)
+ dz[c] = dx[c] + dy[c];
+ } else {
+ for (int c = 0; c < n; c++)
+ dz[c] = da*dx[c] + dy[c];
+ }
+ } else {
+ if (da == 1.0f) {
+ for (int c = 0, xi = dxIdx, yi = dyIdx, zi = dzIdx; c < n; c++, xi += incx, yi += incy, zi += incz) {
+ dz[zi] = dx[xi] + dy[yi];
+ }
+ } else {
+ for (int c = 0, xi = dxIdx, yi = dyIdx, zi = dzIdx; c < n; c++, xi += incx, yi += incy, zi += incz) {
+ dz[zi] = da*dx[xi] + dy[yi];
+ }
+ }
+ }
+ }
+
+ public static void rzgxpy(int n, float[] dz, float[] dx, float[] dy) {
+ for (int c = 0; c < n; c++)
+ dz[c] = dx[c] + dy[c];
+ }
+
+ /** Compute scalar product between dx and dy. */
+ public static float rdot(int n, float[] dx, int dxIdx, int incx, float[] dy, int dyIdx, int incy) {
+ float s = 0.0f;
+ if (incx == 1 && incy == 1 && dxIdx == 0 && dyIdx == 0) {
+ for (int i = 0; i < n; i++)
+ s += dx[i] * dy[i];
+ }
+ else {
+ for (int c = 0, xi = dxIdx, yi = dyIdx; c < n; c++, xi += incx, yi += incy) {
+ s += dx[xi] * dy[yi];
+ }
+ }
+ return s;
+ }
+//END
+}
diff --git a/src/org/jblas/la/MatrixFunctions.java b/src/org/jblas/la/MatrixFunctions.java
new file mode 100644
index 0000000..a82b59b
--- /dev/null
+++ b/src/org/jblas/la/MatrixFunctions.java
@@ -0,0 +1,750 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import java.lang.Math;
+
+/**
+ * This class provides the functions from java.lang.Math for matrices. The
+ * functions are applied to each element of the matrix.
+ *
+ * @author Mikio Braun
+ */
+public class MatrixFunctions {
+
+ /*#
+ def mapfct(f); <<-EOS
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) #{f}(x.get(i)));
+ return x;
+ EOS
+ end
+
+ def cmapfct(f); <<-EOS
+ for (int i = 0; i < x.length; i++)
+ x.put(i, x.get(i).#{f}());
+ return x;
+ EOS
+ end
+ #*/
+
+ /**
+ * Sets all elements in this matrix to their absolute values. Note
+ * that this operation is in-place.
+ * @see MatrixFunctions#abs(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix absi(DoubleMatrix x) {
+ /*# mapfct('Math.abs') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.abs(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ public static ComplexDoubleMatrix absi(ComplexDoubleMatrix x) {
+ /*# cmapfct('abs') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, x.get(i).abs());
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the trigonometric <i>arccosine</i> function element wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#acos(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix acosi(DoubleMatrix x) {
+ /*# mapfct('Math.acos') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.acos(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the trigonometric <i>arcsine</i> function element wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#asin(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix asini(DoubleMatrix x) {
+ /*# mapfct('Math.asin') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.asin(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the trigonometric <i>arctangend</i> function element wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#atan(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix atani(DoubleMatrix x) {
+ /*# mapfct('Math.atan') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.atan(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>cube root</i> function element wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#cbrt(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix cbrti(DoubleMatrix x) {
+ /*# mapfct('Math.cbrt') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.cbrt(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Element-wise round up by applying the <i>ceil</i> function on each
+ * element. Note that this is an in-place operation.
+ * @see MatrixFunctions#ceil(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix ceili(DoubleMatrix x) {
+ /*# mapfct('Math.ceil') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.ceil(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>cosine</i> function element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#cos(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix cosi(DoubleMatrix x) {
+ /*# mapfct('Math.cos') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.cos(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>hyperbolic cosine</i> function element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#cosh(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix coshi(DoubleMatrix x) {
+ /*# mapfct('Math.cosh') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.cosh(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>exponential</i> function element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#exp(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix expi(DoubleMatrix x) {
+ /*# mapfct('Math.exp') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.exp(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Element-wise round down by applying the <i>floor</i> function on each
+ * element. Note that this is an in-place operation.
+ * @see MatrixFunctions#floor(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix floori(DoubleMatrix x) {
+ /*# mapfct('Math.floor') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.floor(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>natural logarithm</i> function element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#log(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix logi(DoubleMatrix x) {
+ /*# mapfct('Math.log') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.log(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>logarithm with basis to 10</i> element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#log10(DoubleMatrix)
+ * @return this matrix
+ */
+ public static DoubleMatrix log10i(DoubleMatrix x) {
+ /*# mapfct('Math.log10') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.log10(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Element-wise power function. Replaces each element with its
+ * power of <tt>d</tt>.Note that this is an in-place operation.
+ * @param d the exponent
+ * @see MatrixFunctions#pow(DoubleMatrix,double)
+ * @return this matrix
+ */
+ public static DoubleMatrix powi(DoubleMatrix x, double d) {
+ if (d == 2.0)
+ return x.muli(x);
+ else {
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.pow(x.get(i), d));
+ return x;
+ }
+ }
+
+ public static DoubleMatrix powi(double base, DoubleMatrix x) {
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.pow(base, x.get(i)));
+ return x;
+ }
+
+ public static DoubleMatrix powi(DoubleMatrix x, DoubleMatrix e) {
+ x.checkLength(e.length);
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.pow(x.get(i), e.get(i)));
+ return x;
+ }
+
+ public static DoubleMatrix signumi(DoubleMatrix x) {
+ /*# mapfct('Math.signum') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.signum(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ public static DoubleMatrix sini(DoubleMatrix x) {
+ /*# mapfct('Math.sin') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.sin(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ public static DoubleMatrix sinhi(DoubleMatrix x) {
+ /*# mapfct('Math.sinh') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.sinh(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+ public static DoubleMatrix sqrti(DoubleMatrix x) {
+ /*# mapfct('Math.sqrt') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.sqrt(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+ public static DoubleMatrix tani(DoubleMatrix x) {
+ /*# mapfct('Math.tan') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.tan(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+ public static DoubleMatrix tanhi(DoubleMatrix x) {
+ /*# mapfct('Math.tanh') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (double) Math.tanh(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Returns a copy of this matrix where all elements are set to their
+ * absolute values.
+ * @see MatrixFunctions#absi(DoubleMatrix)
+ * @return copy of this matrix
+ */
+ public static DoubleMatrix abs(DoubleMatrix x) { return absi(x.dup()); }
+
+ /**
+ * Returns a copy of this matrix where the trigonometric <i>acos</i> function is applied
+ * element wise.
+ * @see MatrixFunctions#acosi(DoubleMatrix)
+ * @return copy of this matrix
+ */
+ public static DoubleMatrix acos(DoubleMatrix x) { return acosi(x.dup()); }
+ public static DoubleMatrix asin(DoubleMatrix x) { return asini(x.dup()); }
+ public static DoubleMatrix atan(DoubleMatrix x) { return atani(x.dup()); }
+ public static DoubleMatrix cbrt(DoubleMatrix x) { return cbrti(x.dup()); }
+ public static DoubleMatrix ceil(DoubleMatrix x) { return ceili(x.dup()); }
+ public static DoubleMatrix cos(DoubleMatrix x) { return cosi(x.dup()); }
+ public static DoubleMatrix cosh(DoubleMatrix x) { return coshi(x.dup()); }
+ public static DoubleMatrix exp(DoubleMatrix x) { return expi(x.dup()); }
+ public static DoubleMatrix floor(DoubleMatrix x) { return floori(x.dup()); }
+ public static DoubleMatrix log(DoubleMatrix x) { return logi(x.dup()); }
+ public static DoubleMatrix log10(DoubleMatrix x) { return log10i(x.dup()); }
+ public static double pow(double x, double y) { return (double)Math.pow(x, y); }
+ public static DoubleMatrix pow(DoubleMatrix x, double e) { return powi(x.dup(), e); }
+ public static DoubleMatrix pow(double b, DoubleMatrix x) { return powi(b, x.dup()); }
+ public static DoubleMatrix pow(DoubleMatrix x, DoubleMatrix e) { return powi(x.dup(), e); }
+ public static DoubleMatrix signum(DoubleMatrix x) { return signumi(x.dup()); }
+ public static DoubleMatrix sin(DoubleMatrix x) { return sini(x.dup()); }
+ public static DoubleMatrix sinh(DoubleMatrix x) { return sinhi(x.dup()); }
+ public static DoubleMatrix sqrt(DoubleMatrix x) { return sqrti(x.dup()); }
+ public static DoubleMatrix tan(DoubleMatrix x) { return tani(x.dup()); }
+ public static DoubleMatrix tanh(DoubleMatrix x) { return tanhi(x.dup()); }
+
+ /*# %w{abs acos asin atan cbrt ceil cos cosh exp floor log log10 signum sin sinh sqrt tan tanh}.map do |fct| <<-EOS
+ public static double #{fct}(double x) { return (double)Math.#{fct}(x); }
+ EOS
+ end
+ #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public static double abs(double x) { return (double)Math.abs(x); }
+ public static double acos(double x) { return (double)Math.acos(x); }
+ public static double asin(double x) { return (double)Math.asin(x); }
+ public static double atan(double x) { return (double)Math.atan(x); }
+ public static double cbrt(double x) { return (double)Math.cbrt(x); }
+ public static double ceil(double x) { return (double)Math.ceil(x); }
+ public static double cos(double x) { return (double)Math.cos(x); }
+ public static double cosh(double x) { return (double)Math.cosh(x); }
+ public static double exp(double x) { return (double)Math.exp(x); }
+ public static double floor(double x) { return (double)Math.floor(x); }
+ public static double log(double x) { return (double)Math.log(x); }
+ public static double log10(double x) { return (double)Math.log10(x); }
+ public static double signum(double x) { return (double)Math.signum(x); }
+ public static double sin(double x) { return (double)Math.sin(x); }
+ public static double sinh(double x) { return (double)Math.sinh(x); }
+ public static double sqrt(double x) { return (double)Math.sqrt(x); }
+ public static double tan(double x) { return (double)Math.tan(x); }
+ public static double tanh(double x) { return (double)Math.tanh(x); }
+//RJPP-END--------------------------------------------------------------
+
+//BEGIN
+ // The code below has been automatically generated.
+ // DO NOT EDIT!
+
+ /*#
+ def mapfct(f); <<-EOS
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) #{f}(x.get(i)));
+ return x;
+ EOS
+ end
+
+ def cmapfct(f); <<-EOS
+ for (int i = 0; i < x.length; i++)
+ x.put(i, x.get(i).#{f}());
+ return x;
+ EOS
+ end
+ #*/
+
+ /**
+ * Sets all elements in this matrix to their absolute values. Note
+ * that this operation is in-place.
+ * @see MatrixFunctions#abs(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix absi(FloatMatrix x) {
+ /*# mapfct('Math.abs') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.abs(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ public static ComplexFloatMatrix absi(ComplexFloatMatrix x) {
+ /*# cmapfct('abs') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, x.get(i).abs());
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the trigonometric <i>arccosine</i> function element wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#acos(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix acosi(FloatMatrix x) {
+ /*# mapfct('Math.acos') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.acos(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the trigonometric <i>arcsine</i> function element wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#asin(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix asini(FloatMatrix x) {
+ /*# mapfct('Math.asin') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.asin(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the trigonometric <i>arctangend</i> function element wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#atan(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix atani(FloatMatrix x) {
+ /*# mapfct('Math.atan') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.atan(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>cube root</i> function element wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#cbrt(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix cbrti(FloatMatrix x) {
+ /*# mapfct('Math.cbrt') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.cbrt(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Element-wise round up by applying the <i>ceil</i> function on each
+ * element. Note that this is an in-place operation.
+ * @see MatrixFunctions#ceil(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix ceili(FloatMatrix x) {
+ /*# mapfct('Math.ceil') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.ceil(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>cosine</i> function element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#cos(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix cosi(FloatMatrix x) {
+ /*# mapfct('Math.cos') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.cos(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>hyperbolic cosine</i> function element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#cosh(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix coshi(FloatMatrix x) {
+ /*# mapfct('Math.cosh') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.cosh(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>exponential</i> function element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#exp(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix expi(FloatMatrix x) {
+ /*# mapfct('Math.exp') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.exp(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Element-wise round down by applying the <i>floor</i> function on each
+ * element. Note that this is an in-place operation.
+ * @see MatrixFunctions#floor(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix floori(FloatMatrix x) {
+ /*# mapfct('Math.floor') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.floor(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>natural logarithm</i> function element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#log(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix logi(FloatMatrix x) {
+ /*# mapfct('Math.log') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.log(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Applies the <i>logarithm with basis to 10</i> element-wise on this
+ * matrix. Note that this is an in-place operation.
+ * @see MatrixFunctions#log10(FloatMatrix)
+ * @return this matrix
+ */
+ public static FloatMatrix log10i(FloatMatrix x) {
+ /*# mapfct('Math.log10') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.log10(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Element-wise power function. Replaces each element with its
+ * power of <tt>d</tt>.Note that this is an in-place operation.
+ * @param d the exponent
+ * @see MatrixFunctions#pow(FloatMatrix,float)
+ * @return this matrix
+ */
+ public static FloatMatrix powi(FloatMatrix x, float d) {
+ if (d == 2.0f)
+ return x.muli(x);
+ else {
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.pow(x.get(i), d));
+ return x;
+ }
+ }
+
+ public static FloatMatrix powi(float base, FloatMatrix x) {
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.pow(base, x.get(i)));
+ return x;
+ }
+
+ public static FloatMatrix powi(FloatMatrix x, FloatMatrix e) {
+ x.checkLength(e.length);
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.pow(x.get(i), e.get(i)));
+ return x;
+ }
+
+ public static FloatMatrix signumi(FloatMatrix x) {
+ /*# mapfct('Math.signum') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.signum(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ public static FloatMatrix sini(FloatMatrix x) {
+ /*# mapfct('Math.sin') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.sin(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ public static FloatMatrix sinhi(FloatMatrix x) {
+ /*# mapfct('Math.sinh') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.sinh(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+ public static FloatMatrix sqrti(FloatMatrix x) {
+ /*# mapfct('Math.sqrt') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.sqrt(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+ public static FloatMatrix tani(FloatMatrix x) {
+ /*# mapfct('Math.tan') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.tan(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+ public static FloatMatrix tanhi(FloatMatrix x) {
+ /*# mapfct('Math.tanh') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ for (int i = 0; i < x.length; i++)
+ x.put(i, (float) Math.tanh(x.get(i)));
+ return x;
+//RJPP-END--------------------------------------------------------------
+ }
+
+ /**
+ * Returns a copy of this matrix where all elements are set to their
+ * absolute values.
+ * @see MatrixFunctions#absi(FloatMatrix)
+ * @return copy of this matrix
+ */
+ public static FloatMatrix abs(FloatMatrix x) { return absi(x.dup()); }
+
+ /**
+ * Returns a copy of this matrix where the trigonometric <i>acos</i> function is applied
+ * element wise.
+ * @see MatrixFunctions#acosi(FloatMatrix)
+ * @return copy of this matrix
+ */
+ public static FloatMatrix acos(FloatMatrix x) { return acosi(x.dup()); }
+ public static FloatMatrix asin(FloatMatrix x) { return asini(x.dup()); }
+ public static FloatMatrix atan(FloatMatrix x) { return atani(x.dup()); }
+ public static FloatMatrix cbrt(FloatMatrix x) { return cbrti(x.dup()); }
+ public static FloatMatrix ceil(FloatMatrix x) { return ceili(x.dup()); }
+ public static FloatMatrix cos(FloatMatrix x) { return cosi(x.dup()); }
+ public static FloatMatrix cosh(FloatMatrix x) { return coshi(x.dup()); }
+ public static FloatMatrix exp(FloatMatrix x) { return expi(x.dup()); }
+ public static FloatMatrix floor(FloatMatrix x) { return floori(x.dup()); }
+ public static FloatMatrix log(FloatMatrix x) { return logi(x.dup()); }
+ public static FloatMatrix log10(FloatMatrix x) { return log10i(x.dup()); }
+ public static float pow(float x, float y) { return (float)Math.pow(x, y); }
+ public static FloatMatrix pow(FloatMatrix x, float e) { return powi(x.dup(), e); }
+ public static FloatMatrix pow(float b, FloatMatrix x) { return powi(b, x.dup()); }
+ public static FloatMatrix pow(FloatMatrix x, FloatMatrix e) { return powi(x.dup(), e); }
+ public static FloatMatrix signum(FloatMatrix x) { return signumi(x.dup()); }
+ public static FloatMatrix sin(FloatMatrix x) { return sini(x.dup()); }
+ public static FloatMatrix sinh(FloatMatrix x) { return sinhi(x.dup()); }
+ public static FloatMatrix sqrt(FloatMatrix x) { return sqrti(x.dup()); }
+ public static FloatMatrix tan(FloatMatrix x) { return tani(x.dup()); }
+ public static FloatMatrix tanh(FloatMatrix x) { return tanhi(x.dup()); }
+
+ /*# %w{abs acos asin atan cbrt ceil cos cosh exp floor log log10 signum sin sinh sqrt tan tanh}.map do |fct| <<-EOS
+ public static float #{fct}(float x) { return (float)Math.#{fct}(x); }
+ EOS
+ end
+ #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public static float abs(float x) { return (float)Math.abs(x); }
+ public static float acos(float x) { return (float)Math.acos(x); }
+ public static float asin(float x) { return (float)Math.asin(x); }
+ public static float atan(float x) { return (float)Math.atan(x); }
+ public static float cbrt(float x) { return (float)Math.cbrt(x); }
+ public static float ceil(float x) { return (float)Math.ceil(x); }
+ public static float cos(float x) { return (float)Math.cos(x); }
+ public static float cosh(float x) { return (float)Math.cosh(x); }
+ public static float exp(float x) { return (float)Math.exp(x); }
+ public static float floor(float x) { return (float)Math.floor(x); }
+ public static float log(float x) { return (float)Math.log(x); }
+ public static float log10(float x) { return (float)Math.log10(x); }
+ public static float signum(float x) { return (float)Math.signum(x); }
+ public static float sin(float x) { return (float)Math.sin(x); }
+ public static float sinh(float x) { return (float)Math.sinh(x); }
+ public static float sqrt(float x) { return (float)Math.sqrt(x); }
+ public static float tan(float x) { return (float)Math.tan(x); }
+ public static float tanh(float x) { return (float)Math.tanh(x); }
+//RJPP-END--------------------------------------------------------------
+
+//END
+}
diff --git a/src/org/jblas/la/SimpleBlas.java b/src/org/jblas/la/SimpleBlas.java
new file mode 100644
index 0000000..ff140fb
--- /dev/null
+++ b/src/org/jblas/la/SimpleBlas.java
@@ -0,0 +1,670 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.exceptions.LapackException;
+import org.jblas.la.exceptions.LapackArgumentException;
+import org.jblas.core.ComplexDouble;
+import org.jblas.core.ComplexFloat;
+import org.jblas.la.exceptions.LapackConvergenceException;
+
+//import edu.ida.core.OutputValue;
+
+/**
+ * This class provides a cleaner direct interface to the BLAS routines by
+ * extracting the parameters of the matrices from the matrices itself.
+ *
+ * For example, you can just pass the vector and do not have to pass the length,
+ * corresponding DoubleBuffer, offset and step size explicitly.
+ *
+ * Currently, all the general matrix routines are implemented.
+ *
+ */
+public class SimpleBlas {
+ /***************************************************************************
+ * BLAS Level 1
+ */
+
+ /** Compute x <-> y (swap two matrices) */
+ public static DoubleMatrix swap(DoubleMatrix x, DoubleMatrix y) {
+ //Blas.dswap(x.length, x.data, 0, 1, y.data, 0, 1);
+ JavaBlas.rswap(x.length, x.data, 0, 1, y.data, 0, 1);
+ return y;
+ }
+
+ /** Compute x <- alpha * x (scale a matrix) */
+ public static DoubleMatrix scal(double alpha, DoubleMatrix x) {
+ Blas.dscal(x.length, alpha, x.data, 0, 1);
+ return x;
+ }
+
+ public static ComplexDoubleMatrix scal(ComplexDouble alpha, ComplexDoubleMatrix x) {
+ Blas.zscal(x.length, alpha, x.data, 0, 1);
+ return x;
+ }
+
+ /** Compute y <- x (copy a matrix) */
+ public static DoubleMatrix copy(DoubleMatrix x, DoubleMatrix y) {
+ //Blas.dcopy(x.length, x.data, 0, 1, y.data, 0, 1);
+ JavaBlas.rcopy(x.length, x.data, 0, 1, y.data, 0, 1);
+ return y;
+ }
+
+ public static ComplexDoubleMatrix copy(ComplexDoubleMatrix x, ComplexDoubleMatrix y) {
+ Blas.zcopy(x.length, x.data, 0, 1, y.data, 0, 1);
+ return y;
+ }
+
+ /** Compute y <- alpha * x + y (elementwise addition) */
+ public static DoubleMatrix axpy(double da, DoubleMatrix dx, DoubleMatrix dy) {
+ //Blas.daxpy(dx.length, da, dx.data, 0, 1, dy.data, 0, 1);
+ JavaBlas.raxpy(dx.length, da, dx.data, 0, 1, dy.data, 0, 1);
+
+ return dy;
+ }
+
+ public static ComplexDoubleMatrix axpy(ComplexDouble da, ComplexDoubleMatrix dx, ComplexDoubleMatrix dy) {
+ Blas.zaxpy(dx.length, da, dx.data, 0, 1, dy.data, 0, 1);
+ return dy;
+ }
+
+ /** Compute x^T * y (dot product) */
+ public static double dot(DoubleMatrix x, DoubleMatrix y) {
+ //return Blas.ddot(x.length, x.data, 0, 1, y.data, 0, 1);
+ return JavaBlas.rdot(x.length, x.data, 0, 1, y.data, 0, 1);
+ }
+
+ /** Compute x^T * y (dot product) */
+ public static ComplexDouble dotc(ComplexDoubleMatrix x, ComplexDoubleMatrix y) {
+ return Blas.zdotc(x.length, x.data, 0, 1, y.data, 0, 1);
+ }
+
+ /** Compute x^T * y (dot product) */
+ public static ComplexDouble dotu(ComplexDoubleMatrix x, ComplexDoubleMatrix y) {
+ return Blas.zdotu(x.length, x.data, 0, 1, y.data, 0, 1);
+ }
+
+ /** Compute || x ||_2 (2-norm) */
+ public static double nrm2(DoubleMatrix x) {
+ return Blas.dnrm2(x.length, x.data, 0, 1);
+ }
+
+ public static double nrm2(ComplexDoubleMatrix x) {
+ return Blas.dznrm2(x.length, x.data, 0, 1);
+ }
+
+ /** Compute || x ||_1 (1-norm, sum of absolute values) */
+ public static double asum(DoubleMatrix x) {
+ return Blas.dasum(x.length, x.data, 0, 1);
+ }
+
+ public static double asum(ComplexDoubleMatrix x) {
+ return Blas.dzasum(x.length, x.data, 0, 1);
+ }
+
+ /**
+ * Compute index of element with largest absolute value (index of absolute
+ * value maximum)
+ */
+ public static int iamax(DoubleMatrix x) {
+ return Blas.idamax(x.length, x.data, 0, 1) - 1;
+ }
+
+ public static int iamax(ComplexDoubleMatrix x) {
+ return Blas.izamax(x.length, x.data, 0, 1);
+ }
+
+ /***************************************************************************
+ * BLAS Level 2
+ */
+
+ /**
+ * Compute y <- alpha*op(a)*x + beta * y (general matrix vector
+ * multiplication)
+ */
+ public static DoubleMatrix gemv(double alpha, DoubleMatrix a,
+ DoubleMatrix x, double beta, DoubleMatrix y) {
+ if (false) {
+ Blas.dgemv('N', a.rows, a.columns, alpha, a.data, 0, a.rows, x.data, 0,
+ 1, beta, y.data, 0, 1);
+ }
+ else {
+ if (beta == 0.0) {
+ for (int i = 0; i < y.length; i++)
+ y.data[i] = 0.0;
+
+ for (int j = 0; j < a.columns; j++)
+ for (int i = 0; i < a.rows; i++)
+ y.data[i] += a.get(i, j) * x.get(j);
+ }
+ else {
+ for (int j = 0; j < a.columns; j++)
+ for (int i = 0; i < a.rows; i++)
+ y.data[j] = a.get(i, j) * x.get(i) + y.data[j];
+ }
+ }
+ return y;
+ }
+
+ /** Compute A <- alpha * x * y^T + A (general rank-1 update) */
+ public static DoubleMatrix ger(double alpha, DoubleMatrix x,
+ DoubleMatrix y, DoubleMatrix a) {
+ Blas.dger(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
+ 0, a.rows);
+ return a;
+ }
+
+ /** Compute A <- alpha * x * y^T + A (general rank-1 update) */
+ public static ComplexDoubleMatrix geru(ComplexDouble alpha, ComplexDoubleMatrix x,
+ ComplexDoubleMatrix y, ComplexDoubleMatrix a) {
+ Blas.zgeru(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
+ 0, a.rows);
+ return a;
+ }
+
+ /** Compute A <- alpha * x * y^H + A (general rank-1 update) */
+ public static ComplexDoubleMatrix gerc(ComplexDouble alpha, ComplexDoubleMatrix x,
+ ComplexDoubleMatrix y, ComplexDoubleMatrix a) {
+ Blas.zgerc(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
+ 0, a.rows);
+ return a;
+ }
+
+ /***************************************************************************
+ * BLAS Level 3
+ */
+
+ /**
+ * Compute c <- a*b + beta * c (general matrix matrix
+ * multiplication)
+ */
+ public static DoubleMatrix gemm(double alpha, DoubleMatrix a,
+ DoubleMatrix b, double beta, DoubleMatrix c) {
+ Blas.dgemm('N', 'N', c.rows, c.columns, a.columns, alpha, a.data, 0,
+ a.rows, b.data, 0, b.rows, beta, c.data, 0, c.rows);
+ return c;
+ }
+
+ public static ComplexDoubleMatrix gemm(ComplexDouble alpha, ComplexDoubleMatrix a,
+ ComplexDoubleMatrix b, ComplexDouble beta, ComplexDoubleMatrix c) {
+ Blas.zgemm('N', 'N', c.rows, c.columns, a.columns, alpha, a.data, 0,
+ a.rows, b.data, 0, b.rows, beta, c.data, 0, c.rows);
+ return c;
+ }
+
+ /***************************************************************************
+ * LAPACK
+ */
+ public static DoubleMatrix gesv(DoubleMatrix a, int[] ipiv,
+ DoubleMatrix b) {
+ int info = Blas.dgesv(a.rows, b.columns, a.data, 0, a.rows, ipiv, 0,
+ b.data, 0, b.rows);
+ checkInfo("DGESV", info);
+
+ if (info > 0)
+ throw new LapackException("DGESV",
+ "Linear equation cannot be solved because the matrix was singular.");
+
+ return b;
+ }
+
+//STOP
+ private static void checkInfo(String name, int info) {
+ if (info < -1)
+ throw new LapackArgumentException(name, info);
+ }
+//START
+
+ public static DoubleMatrix sysv(char uplo, DoubleMatrix a, int[] ipiv,
+ DoubleMatrix b) {
+ int info = Blas.dsysv(uplo, a.rows, b.columns, a.data, 0, a.rows, ipiv, 0,
+ b.data, 0, b.rows);
+ checkInfo("DSYSV", info);
+
+ if (info > 0)
+ throw new IllegalArgumentException(
+ "Linear equation cannot be solved because the matrix was singular.");
+
+ return b;
+ }
+
+ public static int syev(char jobz, char uplo, DoubleMatrix a, DoubleMatrix w) {
+ double[] work = new double[1];
+ int info = Blas.dsyev(jobz, uplo, a.rows, a.data, 0, a.rows, w.data, 0,
+ work, 0, -1);
+ checkInfo("DSYEV", info);
+
+ int lwork = (int) work[0];
+ work = new double[lwork];
+
+ // System.out.println("Optimal LWORK = " + lwork);
+
+ info = Blas.dsyev(jobz, uplo, a.rows, a.data, 0, a.rows, w.data, 0,
+ work, 0, lwork);
+
+ if (info > 0)
+ throw new IllegalArgumentException(
+ "Eigenvalues could not be computed " + info
+ + " off-diagonal elements did not converge");
+
+ return info;
+ }
+
+ public static int syevx(char jobz, char range, char uplo, DoubleMatrix a,
+ double vl, double vu, int il, int iu, double abstol,
+ DoubleMatrix w, DoubleMatrix z) {
+ int n = a.rows;
+ int[] iwork = new int[5 * n];
+ int[] ifail = new int[n];
+ int[] m = new int[1];
+ int info;
+
+ info = Blas.dsyevx(jobz, range, uplo, n, a.data, 0, a.rows, vl, vu, il,
+ iu, abstol, m, 0, w.data, 0, z.data, 0, z.rows, iwork, 0, ifail, 0);
+
+ //System.out.printf("found eigenvalues = %d\n", m[0]);
+
+ if (info > 0) {
+ StringBuilder msg = new StringBuilder();
+ msg
+ .append("Not all eigenvalues converged. Non-converging eigenvalues were: ");
+ for (int i = 0; i < info; i++) {
+ if (i > 0)
+ msg.append(", ");
+ msg.append(ifail[i]);
+ }
+ msg.append(".");
+ throw new IllegalArgumentException(msg.toString());
+ }
+
+ return info;
+ }
+
+ public static int syevd(char jobz, char uplo, DoubleMatrix A,
+ DoubleMatrix w) {
+ int n = A.rows;
+
+ int info = Blas.dsyevd(jobz, uplo, n, A.data, 0, A.rows, w.data, 0);
+
+ if (info > 0)
+ throw new LapackConvergenceException("SYEVD", "Not all eigenvalues converged.");
+
+ return info;
+ }
+
+ public static int syevr(char jobz, char range, char uplo, DoubleMatrix a,
+ double vl, double vu, int il, int iu, double abstol,
+ DoubleMatrix w, DoubleMatrix z, int[] isuppz) {
+ int n = a.rows;
+ int[] m = new int[1];
+
+ int info = Blas.dsyevr(jobz, range, uplo, n, a.data, 0, a.rows, vl, vu,
+ il, iu, abstol, m, 0, w.data, 0, z.data, 0, z.rows, isuppz, 0);
+
+ //System.out.printf("found eigenvalues = %d\n", m[0]);
+
+ checkInfo("SYEVR", info);
+
+ return info;
+ }
+
+ public static void posv(char uplo, DoubleMatrix A, DoubleMatrix B) {
+ int n = A.rows;
+ int nrhs = B.columns;
+ int info = Blas.dposv(uplo, n, nrhs, A.data, 0, A.rows, B.data, 0,
+ B.rows);
+ checkInfo("DPOSV", info);
+ if (info > 0)
+ throw new LapackException("DPOSV",
+ "Leading minor of order i of A is not positive definite.");
+ }
+
+ public static int geev(char jobvl, char jobvr, DoubleMatrix A,
+ DoubleMatrix WR, DoubleMatrix WI, DoubleMatrix VL, DoubleMatrix VR) {
+ int info = Blas.dgeev(jobvl, jobvr, A.rows, A.data, 0, A.rows, WR.data, 0,
+ WI.data, 0, VL.data, 0, VL.rows, VR.data, 0, VR.rows);
+ if (info > 0)
+ throw new LapackException("DGEEV", "First " + info + " eigenvalues have not converged.");
+ return info;
+ }
+
+//BEGIN
+ // The code below has been automatically generated.
+ // DO NOT EDIT!
+ /***************************************************************************
+ * BLAS Level 1
+ */
+
+ /** Compute x <-> y (swap two matrices) */
+ public static FloatMatrix swap(FloatMatrix x, FloatMatrix y) {
+ //Blas.sswap(x.length, x.data, 0, 1, y.data, 0, 1);
+ JavaBlas.rswap(x.length, x.data, 0, 1, y.data, 0, 1);
+ return y;
+ }
+
+ /** Compute x <- alpha * x (scale a matrix) */
+ public static FloatMatrix scal(float alpha, FloatMatrix x) {
+ Blas.sscal(x.length, alpha, x.data, 0, 1);
+ return x;
+ }
+
+ public static ComplexFloatMatrix scal(ComplexFloat alpha, ComplexFloatMatrix x) {
+ Blas.cscal(x.length, alpha, x.data, 0, 1);
+ return x;
+ }
+
+ /** Compute y <- x (copy a matrix) */
+ public static FloatMatrix copy(FloatMatrix x, FloatMatrix y) {
+ //Blas.scopy(x.length, x.data, 0, 1, y.data, 0, 1);
+ JavaBlas.rcopy(x.length, x.data, 0, 1, y.data, 0, 1);
+ return y;
+ }
+
+ public static ComplexFloatMatrix copy(ComplexFloatMatrix x, ComplexFloatMatrix y) {
+ Blas.ccopy(x.length, x.data, 0, 1, y.data, 0, 1);
+ return y;
+ }
+
+ /** Compute y <- alpha * x + y (elementwise addition) */
+ public static FloatMatrix axpy(float da, FloatMatrix dx, FloatMatrix dy) {
+ //Blas.saxpy(dx.length, da, dx.data, 0, 1, dy.data, 0, 1);
+ JavaBlas.raxpy(dx.length, da, dx.data, 0, 1, dy.data, 0, 1);
+
+ return dy;
+ }
+
+ public static ComplexFloatMatrix axpy(ComplexFloat da, ComplexFloatMatrix dx, ComplexFloatMatrix dy) {
+ Blas.caxpy(dx.length, da, dx.data, 0, 1, dy.data, 0, 1);
+ return dy;
+ }
+
+ /** Compute x^T * y (dot product) */
+ public static float dot(FloatMatrix x, FloatMatrix y) {
+ //return Blas.sdot(x.length, x.data, 0, 1, y.data, 0, 1);
+ return JavaBlas.rdot(x.length, x.data, 0, 1, y.data, 0, 1);
+ }
+
+ /** Compute x^T * y (dot product) */
+ public static ComplexFloat dotc(ComplexFloatMatrix x, ComplexFloatMatrix y) {
+ return Blas.cdotc(x.length, x.data, 0, 1, y.data, 0, 1);
+ }
+
+ /** Compute x^T * y (dot product) */
+ public static ComplexFloat dotu(ComplexFloatMatrix x, ComplexFloatMatrix y) {
+ return Blas.cdotu(x.length, x.data, 0, 1, y.data, 0, 1);
+ }
+
+ /** Compute || x ||_2 (2-norm) */
+ public static float nrm2(FloatMatrix x) {
+ return Blas.snrm2(x.length, x.data, 0, 1);
+ }
+
+ public static float nrm2(ComplexFloatMatrix x) {
+ return Blas.scnrm2(x.length, x.data, 0, 1);
+ }
+
+ /** Compute || x ||_1 (1-norm, sum of absolute values) */
+ public static float asum(FloatMatrix x) {
+ return Blas.sasum(x.length, x.data, 0, 1);
+ }
+
+ public static float asum(ComplexFloatMatrix x) {
+ return Blas.scasum(x.length, x.data, 0, 1);
+ }
+
+ /**
+ * Compute index of element with largest absolute value (index of absolute
+ * value maximum)
+ */
+ public static int iamax(FloatMatrix x) {
+ return Blas.isamax(x.length, x.data, 0, 1) - 1;
+ }
+
+ public static int iamax(ComplexFloatMatrix x) {
+ return Blas.icamax(x.length, x.data, 0, 1);
+ }
+
+ /***************************************************************************
+ * BLAS Level 2
+ */
+
+ /**
+ * Compute y <- alpha*op(a)*x + beta * y (general matrix vector
+ * multiplication)
+ */
+ public static FloatMatrix gemv(float alpha, FloatMatrix a,
+ FloatMatrix x, float beta, FloatMatrix y) {
+ if (false) {
+ Blas.sgemv('N', a.rows, a.columns, alpha, a.data, 0, a.rows, x.data, 0,
+ 1, beta, y.data, 0, 1);
+ }
+ else {
+ if (beta == 0.0f) {
+ for (int i = 0; i < y.length; i++)
+ y.data[i] = 0.0f;
+
+ for (int j = 0; j < a.columns; j++)
+ for (int i = 0; i < a.rows; i++)
+ y.data[i] += a.get(i, j) * x.get(j);
+ }
+ else {
+ for (int j = 0; j < a.columns; j++)
+ for (int i = 0; i < a.rows; i++)
+ y.data[j] = a.get(i, j) * x.get(i) + y.data[j];
+ }
+ }
+ return y;
+ }
+
+ /** Compute A <- alpha * x * y^T + A (general rank-1 update) */
+ public static FloatMatrix ger(float alpha, FloatMatrix x,
+ FloatMatrix y, FloatMatrix a) {
+ Blas.sger(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
+ 0, a.rows);
+ return a;
+ }
+
+ /** Compute A <- alpha * x * y^T + A (general rank-1 update) */
+ public static ComplexFloatMatrix geru(ComplexFloat alpha, ComplexFloatMatrix x,
+ ComplexFloatMatrix y, ComplexFloatMatrix a) {
+ Blas.cgeru(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
+ 0, a.rows);
+ return a;
+ }
+
+ /** Compute A <- alpha * x * y^H + A (general rank-1 update) */
+ public static ComplexFloatMatrix gerc(ComplexFloat alpha, ComplexFloatMatrix x,
+ ComplexFloatMatrix y, ComplexFloatMatrix a) {
+ Blas.cgerc(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
+ 0, a.rows);
+ return a;
+ }
+
+ /***************************************************************************
+ * BLAS Level 3
+ */
+
+ /**
+ * Compute c <- a*b + beta * c (general matrix matrix
+ * multiplication)
+ */
+ public static FloatMatrix gemm(float alpha, FloatMatrix a,
+ FloatMatrix b, float beta, FloatMatrix c) {
+ Blas.sgemm('N', 'N', c.rows, c.columns, a.columns, alpha, a.data, 0,
+ a.rows, b.data, 0, b.rows, beta, c.data, 0, c.rows);
+ return c;
+ }
+
+ public static ComplexFloatMatrix gemm(ComplexFloat alpha, ComplexFloatMatrix a,
+ ComplexFloatMatrix b, ComplexFloat beta, ComplexFloatMatrix c) {
+ Blas.cgemm('N', 'N', c.rows, c.columns, a.columns, alpha, a.data, 0,
+ a.rows, b.data, 0, b.rows, beta, c.data, 0, c.rows);
+ return c;
+ }
+
+ /***************************************************************************
+ * LAPACK
+ */
+ public static FloatMatrix gesv(FloatMatrix a, int[] ipiv,
+ FloatMatrix b) {
+ int info = Blas.sgesv(a.rows, b.columns, a.data, 0, a.rows, ipiv, 0,
+ b.data, 0, b.rows);
+ checkInfo("DGESV", info);
+
+ if (info > 0)
+ throw new LapackException("DGESV",
+ "Linear equation cannot be solved because the matrix was singular.");
+
+ return b;
+ }
+
+
+ public static FloatMatrix sysv(char uplo, FloatMatrix a, int[] ipiv,
+ FloatMatrix b) {
+ int info = Blas.ssysv(uplo, a.rows, b.columns, a.data, 0, a.rows, ipiv, 0,
+ b.data, 0, b.rows);
+ checkInfo("DSYSV", info);
+
+ if (info > 0)
+ throw new IllegalArgumentException(
+ "Linear equation cannot be solved because the matrix was singular.");
+
+ return b;
+ }
+
+ public static int syev(char jobz, char uplo, FloatMatrix a, FloatMatrix w) {
+ float[] work = new float[1];
+ int info = Blas.ssyev(jobz, uplo, a.rows, a.data, 0, a.rows, w.data, 0,
+ work, 0, -1);
+ checkInfo("DSYEV", info);
+
+ int lwork = (int) work[0];
+ work = new float[lwork];
+
+ // System.out.println("Optimal LWORK = " + lwork);
+
+ info = Blas.ssyev(jobz, uplo, a.rows, a.data, 0, a.rows, w.data, 0,
+ work, 0, lwork);
+
+ if (info > 0)
+ throw new IllegalArgumentException(
+ "Eigenvalues could not be computed " + info
+ + " off-diagonal elements did not converge");
+
+ return info;
+ }
+
+ public static int syevx(char jobz, char range, char uplo, FloatMatrix a,
+ float vl, float vu, int il, int iu, float abstol,
+ FloatMatrix w, FloatMatrix z) {
+ int n = a.rows;
+ int[] iwork = new int[5 * n];
+ int[] ifail = new int[n];
+ int[] m = new int[1];
+ int info;
+
+ info = Blas.ssyevx(jobz, range, uplo, n, a.data, 0, a.rows, vl, vu, il,
+ iu, abstol, m, 0, w.data, 0, z.data, 0, z.rows, iwork, 0, ifail, 0);
+
+ //System.out.printf("found eigenvalues = %d\n", m[0]);
+
+ if (info > 0) {
+ StringBuilder msg = new StringBuilder();
+ msg
+ .append("Not all eigenvalues converged. Non-converging eigenvalues were: ");
+ for (int i = 0; i < info; i++) {
+ if (i > 0)
+ msg.append(", ");
+ msg.append(ifail[i]);
+ }
+ msg.append(".");
+ throw new IllegalArgumentException(msg.toString());
+ }
+
+ return info;
+ }
+
+ public static int syevd(char jobz, char uplo, FloatMatrix A,
+ FloatMatrix w) {
+ int n = A.rows;
+
+ int info = Blas.ssyevd(jobz, uplo, n, A.data, 0, A.rows, w.data, 0);
+
+ if (info > 0)
+ throw new LapackConvergenceException("SYEVD", "Not all eigenvalues converged.");
+
+ return info;
+ }
+
+ public static int syevr(char jobz, char range, char uplo, FloatMatrix a,
+ float vl, float vu, int il, int iu, float abstol,
+ FloatMatrix w, FloatMatrix z, int[] isuppz) {
+ int n = a.rows;
+ int[] m = new int[1];
+
+ int info = Blas.ssyevr(jobz, range, uplo, n, a.data, 0, a.rows, vl, vu,
+ il, iu, abstol, m, 0, w.data, 0, z.data, 0, z.rows, isuppz, 0);
+
+ //System.out.printf("found eigenvalues = %d\n", m[0]);
+
+ checkInfo("SYEVR", info);
+
+ return info;
+ }
+
+ public static void posv(char uplo, FloatMatrix A, FloatMatrix B) {
+ int n = A.rows;
+ int nrhs = B.columns;
+ int info = Blas.sposv(uplo, n, nrhs, A.data, 0, A.rows, B.data, 0,
+ B.rows);
+ checkInfo("DPOSV", info);
+ if (info > 0)
+ throw new LapackException("DPOSV",
+ "Leading minor of order i of A is not positive definite.");
+ }
+
+ public static int geev(char jobvl, char jobvr, FloatMatrix A,
+ FloatMatrix WR, FloatMatrix WI, FloatMatrix VL, FloatMatrix VR) {
+ int info = Blas.sgeev(jobvl, jobvr, A.rows, A.data, 0, A.rows, WR.data, 0,
+ WI.data, 0, VL.data, 0, VL.rows, VR.data, 0, VR.rows);
+ if (info > 0)
+ throw new LapackException("DGEEV", "First " + info + " eigenvalues have not converged.");
+ return info;
+ }
+
+//END
+}
diff --git a/src/org/jblas/la/Solve.java b/src/org/jblas/la/Solve.java
new file mode 100644
index 0000000..cf6830e
--- /dev/null
+++ b/src/org/jblas/la/Solve.java
@@ -0,0 +1,101 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+/**
+ * Solving linear equations.
+ */
+public class Solve {
+ /* Solves the linear equation A*X = B. */
+ public static DoubleMatrix solve(DoubleMatrix A, DoubleMatrix B) {
+ A.assertSquare();
+ DoubleMatrix X = B.dup();
+ int[] ipiv = new int[B.rows];
+ SimpleBlas.gesv(A.dup(), ipiv, X);
+ return X;
+ }
+
+ /* Solves the linear equation A*X = B for symmetric A. */
+ public static DoubleMatrix solveSymmetric(DoubleMatrix A, DoubleMatrix B) {
+ A.assertSquare();
+ DoubleMatrix X = B.dup();
+ int[] ipiv = new int[B.rows];
+ SimpleBlas.sysv('U', A.dup(), ipiv, X);
+ return X;
+ }
+
+
+ /* Solves the linear equation A*X = B for symmetric and positive definite A. */
+ public static DoubleMatrix solvePositive(DoubleMatrix A, DoubleMatrix B) {
+ A.assertSquare();
+ DoubleMatrix X = B.dup();
+ SimpleBlas.posv('U', A.dup(), X);
+ return X;
+ }
+
+//BEGIN
+ // The code below has been automatically generated.
+ // DO NOT EDIT!
+ /* Solves the linear equation A*X = B. */
+ public static FloatMatrix solve(FloatMatrix A, FloatMatrix B) {
+ A.assertSquare();
+ FloatMatrix X = B.dup();
+ int[] ipiv = new int[B.rows];
+ SimpleBlas.gesv(A.dup(), ipiv, X);
+ return X;
+ }
+
+ /* Solves the linear equation A*X = B for symmetric A. */
+ public static FloatMatrix solveSymmetric(FloatMatrix A, FloatMatrix B) {
+ A.assertSquare();
+ FloatMatrix X = B.dup();
+ int[] ipiv = new int[B.rows];
+ SimpleBlas.sysv('U', A.dup(), ipiv, X);
+ return X;
+ }
+
+
+ /* Solves the linear equation A*X = B for symmetric and positive definite A. */
+ public static FloatMatrix solvePositive(FloatMatrix A, FloatMatrix B) {
+ A.assertSquare();
+ FloatMatrix X = B.dup();
+ SimpleBlas.posv('U', A.dup(), X);
+ return X;
+ }
+
+//END
+}
diff --git a/src/org/jblas/la/Trigonometry.java b/src/org/jblas/la/Trigonometry.java
new file mode 100644
index 0000000..1ec4768
--- /dev/null
+++ b/src/org/jblas/la/Trigonometry.java
@@ -0,0 +1,67 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * jBLAS - Light-weight wrapper for ATLAS and LAPACK (http://www.jBLAS.org)
+ *
+ * Copyright (C) 2008 jBLAS Project
+ *
+ * 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:
+ * http://www.gnu.org/copyleft/lesser.html#TOC3
+ *
+ * Created on May 25, 2008
+ * $Id$
+ */
+package org.jblas.la;
+
+/**
+ * Container for trigonometric functions on vectors and matrices.
+ *
+ * @author Johannes Schaback, last edited by $Author$, $Date$
+ * @version $Revision$
+ */
+public class Trigonometry
+{
+ // yet to be filled
+}
diff --git a/src/org/jblas/la/exceptions/LapackArgumentException.java b/src/org/jblas/la/exceptions/LapackArgumentException.java
new file mode 100644
index 0000000..376bc68
--- /dev/null
+++ b/src/org/jblas/la/exceptions/LapackArgumentException.java
@@ -0,0 +1,52 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la.exceptions;
+
+/**
+ * LapackException for a specific argument. LAPACK routines routinely check
+ * whether some arguments contain illegal arguments. This exception class
+ * automatically constructs a message for a given argument index.
+ */
+public class LapackArgumentException extends LapackException {
+ /**
+ * Construct exception for given function and info. Message
+ * will read "Argument <info> had an illegal value.");
+ */
+ public LapackArgumentException(String function, int info) {
+ super(function, "Argument " + info + " had an illegal value.");
+ }
+}
diff --git a/src/org/jblas/la/exceptions/LapackConvergenceException.java b/src/org/jblas/la/exceptions/LapackConvergenceException.java
new file mode 100644
index 0000000..23b1703
--- /dev/null
+++ b/src/org/jblas/la/exceptions/LapackConvergenceException.java
@@ -0,0 +1,53 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la.exceptions;
+
+/**
+ *
+ * @author mikio
+ */
+public class LapackConvergenceException extends LapackException {
+ public LapackConvergenceException(String function, String msg) {
+ super(function, msg);
+ }
+
+}
diff --git a/src/org/jblas/la/exceptions/LapackException.java b/src/org/jblas/la/exceptions/LapackException.java
new file mode 100644
index 0000000..5ebd04a
--- /dev/null
+++ b/src/org/jblas/la/exceptions/LapackException.java
@@ -0,0 +1,53 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la.exceptions;
+
+/**
+ * Base class for all exceptions within LAPACK. Also reports the function where the
+ * error is.
+ */
+public class LapackException extends RuntimeException {
+ /** Construct new LapackException for the given function. */
+ public LapackException(String function) {
+ super("LAPACK " + function);
+ }
+
+ /** Construct new Lapack Exception for the given function, with message. */
+ public LapackException(String function, String message) {
+ super("LAPACK " + function + ": " + message);
+ }
+}
diff --git a/src/org/jblas/la/exceptions/SizeException.java b/src/org/jblas/la/exceptions/SizeException.java
new file mode 100644
index 0000000..2287fa6
--- /dev/null
+++ b/src/org/jblas/la/exceptions/SizeException.java
@@ -0,0 +1,43 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la.exceptions;
+
+public class SizeException extends RuntimeException {
+ public SizeException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/jblas/la/exceptions/package-info.java b/src/org/jblas/la/exceptions/package-info.java
new file mode 100644
index 0000000..13d918c
--- /dev/null
+++ b/src/org/jblas/la/exceptions/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * jblas related exceptions.
+ */
+
+package org.jblas.la.exceptions;
\ No newline at end of file
diff --git a/src/org/jblas/la/package-info.java b/src/org/jblas/la/package-info.java
new file mode 100644
index 0000000..34c96f9
--- /dev/null
+++ b/src/org/jblas/la/package-info.java
@@ -0,0 +1,42 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/**
+ * Main linear algebra package.
+ *
+ * This package contains the linear algebra packages from jBLAS.
+ */
+package org.jblas.la;
diff --git a/src/org/jblas/la/ranges/AllRange.java b/src/org/jblas/la/ranges/AllRange.java
new file mode 100644
index 0000000..101f5af
--- /dev/null
+++ b/src/org/jblas/la/ranges/AllRange.java
@@ -0,0 +1,85 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la.ranges;
+
+import org.jblas.la.*;
+
+/**
+ * A range over all available indices. Can be used to address whole columns or rows. Like
+ * the ":" index in matlab. Don't forget to call init() before using this range.
+ */
+public class AllRange implements Range {
+ private int lower;
+ private int upper;
+ private int value;
+ private int counter;
+
+ public AllRange() {}
+
+ public void init(int l, int u) {
+ lower = l;
+ upper = u;
+ value = l;
+ counter = 0;
+ }
+
+ public int length() {
+ return upper - lower + 1;
+ }
+
+ public int value() {
+ return value;
+ }
+
+ public int index() {
+ return counter;
+ }
+
+ public void next() {
+ counter++;
+ value++;
+ }
+
+ public boolean hasMore() {
+ return value < upper;
+ }
+}
diff --git a/src/org/jblas/la/ranges/IndicesRange.java b/src/org/jblas/la/ranges/IndicesRange.java
new file mode 100644
index 0000000..fffa712
--- /dev/null
+++ b/src/org/jblas/la/ranges/IndicesRange.java
@@ -0,0 +1,95 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la.ranges;
+
+import org.jblas.la.*;
+
+/**
+ * Range which varies over pre-specified indices.
+ *
+ * For example,
+ * <pre>
+ * int[] indices = new int[] { 1, 1, 2, 3, 5, 8, 13 };
+ * Range r = new IndicesRange(indices);</pre>
+ * ranges over the first few Fibonacci numbers.
+ */
+public class IndicesRange implements Range {
+ private int[] indices;
+ private int counter;
+
+ /** Initialize from integer array. */
+ public IndicesRange(int[] is) {
+ indices = is;
+ }
+
+ public void init(int l, int u) {
+ counter = 0;
+ }
+
+ /**
+ * Initialize from DoubleMatrix. Entries are converted to integers
+ * by truncation.
+ */
+ public IndicesRange(DoubleMatrix is) {
+ this(is.toIntArray());
+ }
+
+ public int length() {
+ return indices.length;
+ }
+
+ public void next() {
+ counter++;
+ }
+
+ public int index() {
+ return counter;
+ }
+
+ public int value() {
+ return indices[counter];
+ }
+
+ public boolean hasMore() {
+ return counter < indices.length;
+ }
+}
diff --git a/src/org/jblas/la/ranges/IntervalRange.java b/src/org/jblas/la/ranges/IntervalRange.java
new file mode 100644
index 0000000..909c639
--- /dev/null
+++ b/src/org/jblas/la/ranges/IntervalRange.java
@@ -0,0 +1,86 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.jblas.la.ranges;
+
+/**
+ * Range which varies from a given interval. Endpoints are both inclusive!
+ */
+public class IntervalRange implements Range {
+ private int start;
+ private int end;
+ private int value;
+ private int counter;
+
+ /** Construct new interval range. Endpoints are inclusive. */
+ public IntervalRange(int a, int b) {
+ start = a;
+ end = b;
+ }
+
+ public void init(int lower, int upper) {
+ value = start;
+ counter = 0;
+ if (start < lower || end > upper) {
+ throw new IllegalArgumentException("Bounds " + lower + " to " + upper + " are beyond range interval " + start + " to " + end + ".");
+ }
+ }
+
+ public int length() {
+ return end - start + 1;
+ }
+
+ public void next() {
+ counter++;
+ value++;
+ }
+
+ public int index() {
+ return counter;
+ }
+
+ public int value() {
+ return value;
+ }
+
+ public boolean hasMore() {
+ return counter < end;
+ }
+}
diff --git a/src/org/jblas/la/ranges/PointRange.java b/src/org/jblas/la/ranges/PointRange.java
new file mode 100644
index 0000000..a14ec86
--- /dev/null
+++ b/src/org/jblas/la/ranges/PointRange.java
@@ -0,0 +1,79 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la.ranges;
+
+/**
+ * A PointRange is a range which only has a single point.
+ */
+public class PointRange implements Range {
+ private int value;
+ private boolean consumed;
+
+ /** Construct a new PointRange with the one given index. */
+ public PointRange(int v) {
+ value = v;
+ }
+
+ public void init(int l, int u) {
+ consumed = false;
+ }
+
+ public int length() {
+ return 1;
+ }
+
+ public int value() {
+ return value;
+ }
+
+ public int index() {
+ return 0;
+ }
+
+ public void next() {
+ consumed = true;
+ }
+
+ public boolean hasMore() {
+ return !consumed;
+ }
+}
diff --git a/src/org/jblas/la/ranges/Range.java b/src/org/jblas/la/ranges/Range.java
new file mode 100644
index 0000000..ef784b1
--- /dev/null
+++ b/src/org/jblas/la/ranges/Range.java
@@ -0,0 +1,77 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la.ranges;
+
+/**
+ * <p>The Range interface represents basically a set of indices. Before using a range
+ * you have to call init() with the actually available lower and upper bounds, such
+ * that you can also have an "AllRange" which contains all possible indices.</p>
+ *
+ * <p>Further operations include:</p>
+ *
+ * <ul>
+ * <li> length() - returns total number of elements.
+ * <li> next() - increase counter (use value()) to retrieve the value.
+ * <li> index() - get the index of the current value.
+ * <li> value() - get the current value.
+ * <li> hasMore() - more indices available.
+ * </ul>
+ *
+ * <p>Typical uses look like this:</p>
+ * <pre> for (r.init(lower, upper); r.hasMore(); r.next()) {
+ * System.out.printf("Value number %d is %d%n", index(), value());
+ * }</pre>
+ */
+public interface Range {
+ /** Initialize Range to available indices */
+ public void init(int lower, int upper);
+ /** Total number of indices. */
+ public int length();
+ /** Increase counter. */
+ public void next();
+ /** Consecutive numbering of current index. */
+ public int index();
+ /** Get current index. */
+ public int value();
+ /** More indices available? */
+ public boolean hasMore();
+}
diff --git a/src/org/jblas/la/ranges/RangeUtils.java b/src/org/jblas/la/ranges/RangeUtils.java
new file mode 100644
index 0000000..7a5ece9
--- /dev/null
+++ b/src/org/jblas/la/ranges/RangeUtils.java
@@ -0,0 +1,86 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la.ranges;
+
+import org.jblas.la.*;
+import org.jblas.la.ranges.IndicesRange;
+import org.jblas.la.ranges.AllRange;
+
+/**
+ * A bunch of static functions for making construction of ranges more
+ * uniform. Basically, we have
+ * <ul>
+ * <li>point(3) - a PointRange.
+ * <li>indices(new int[] {1,2,3,...}) - a Indices Range.
+ * <li>interval(1, 2) - an interval range.
+ * <li>all() - an AllRange.
+ * <li>indices(x) - with a DoubleMatrix.
+ * <li>find(x) - an index constructed from the non-zero elements of x.
+ * </ul>
+ *
+ */
+public class RangeUtils {
+ /** Construct point range (constant range) with given index. */
+ public static Range point(int i) {
+ return new PointRange(i);
+ }
+
+ public static Range indices(int[] is) {
+ return new IndicesRange(is);
+ }
+
+ public static Range interval(int a, int b) {
+ return new IntervalRange(a, b);
+ }
+
+ public static Range all() {
+ return new AllRange();
+ }
+
+ public static Range indices(DoubleMatrix is) {
+ return new IndicesRange(is);
+ }
+
+ public static Range find(DoubleMatrix is) {
+ return new IndicesRange(is.findIndices());
+ }
+}
diff --git a/src/org/jblas/la/ranges/package-info.java b/src/org/jblas/la/ranges/package-info.java
new file mode 100644
index 0000000..2a9747b
--- /dev/null
+++ b/src/org/jblas/la/ranges/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Provide ways to specify indices ranges.
+ */
+
+package org.jblas.la.ranges;
\ No newline at end of file
diff --git a/src/org/jblas/util/LibraryLoader.java b/src/org/jblas/util/LibraryLoader.java
new file mode 100644
index 0000000..91d73f3
--- /dev/null
+++ b/src/org/jblas/util/LibraryLoader.java
@@ -0,0 +1,111 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.util;
+
+import java.io.*;
+
+/**
+ * Class which allows to load a dynamic file as resource (for example, from a
+ * jar-file)
+ */
+public class LibraryLoader {
+ /** Find the library <tt>libname</tt> as a resource, copy it to a tempfile
+ * and load it using System.load(). The name of the library has to be the
+ * base name, it is mapped to the corresponding system name using
+ * System.mapLibraryName(). For example, the library "foo" is called "libfoo.so"
+ * under Linux and "foo.dll" under Windows, but you just have to pass "foo"
+ * the loadLibrary().
+ *
+ * I'm not quite sure if this doesn't open all kinds of security holes. Any ideas?
+ *
+ * @param libname basename of the library
+ */
+ public void loadLibrary(String libname) {
+ libname = System.mapLibraryName(libname);
+
+ // We're in a static initializer and need a class. What shall we do?
+ Class cl = getClass();
+
+ InputStream is = cl.getResourceAsStream("/" + libname);
+
+ // Hm, let's see if we can find it in the build directory
+ if (is == null)
+ is = cl.getResourceAsStream("/bin/" + libname);
+
+ if (is == null) {
+ System.err.println("Couldn't find the resource " + libname + ".");
+ System.exit(0);
+ }
+
+ try {
+ File tempfile = File.createTempFile("jblas", libname);
+ tempfile.deleteOnExit();
+ OutputStream os = new FileOutputStream(tempfile);
+
+ System.out.println("tempfile.getPath() = " + tempfile.getPath());
+
+ long savedTime = System.currentTimeMillis();
+
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = is.read(buf)) > 0) {
+ os.write(buf, 0, len);
+ }
+
+ double seconds = (double) (System.currentTimeMillis() - savedTime) / 1e3;
+ System.out.println("Copying took " + seconds + " seconds.");
+
+ os.close();
+
+ System.load(tempfile.getPath());
+ } catch (IOException io) {
+ System.err.println("Could not create the temp file: " + io.toString() + ".\n");
+ } catch (UnsatisfiedLinkError ule) {
+ System.err.println("Couldn't load copied link file: " + ule.toString() + ".\n");
+ }
+ }
+
+ /** Compute the path to the library. The path is basically
+ "/" + os.name + "/" + os.arch + "/" + libname. */
+ static public String libraryPath(String libname) {
+ return "/" + System.getProperty("os.name") + "/" + System.getProperty("os.arch") + "/" + libname;
+ }
+
+ static public void main(String[] args) {
+ System.out.println(libraryPath(""));
+ }
+}
diff --git a/src/org/jblas/util/package-info.java b/src/org/jblas/util/package-info.java
new file mode 100644
index 0000000..78d8641
--- /dev/null
+++ b/src/org/jblas/util/package-info.java
@@ -0,0 +1,42 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/**
+ * Support classes for jBLAS.
+ *
+ * This package contains several support classes.
+ */
+package org.jblas.util;
diff --git a/src/overview.html b/src/overview.html
new file mode 100644
index 0000000..8ade4de
--- /dev/null
+++ b/src/overview.html
@@ -0,0 +1,90 @@
+<html><body><h1>jblas – Linear Algebra for Java</h1>
+<p><em>If you are really impatient, I’d suggest you read the Classes
+Overview below and otherwise stick to the <span class="caps">API</span> Documentation for the
+classes like <a href="org/jblas/la/DoubleMatrix.html">DoubleMatrix</a>.</em></p>
+<p>The main goals of jblas were to provide very high performance, close
+to what you get from state-of-the-art <span class="caps">BLAS</span> and <span class="caps">LAPACK</span> libraries, and
+easy of use, which means that in the ideal case, you can just
+mechanically translate a matrix expression from formulas to Java
+code.</p>
+<p>In all brevity, here is what you need to know to get started:</p>
+<ul>
+ <li>There exist four classes: <a href="org/jblas/la/ComplexFloatMatrix.html">FloatMatrix</a>, <a href="org/jblas/la/DoubleMatrix.html">DoubleMatrix</a>,
+ <a href="org/jblas/la/ComplexFloatMatrix.html">ComplexFloatMatrix</a> and <a href="org/jblas/la/ComplexDoubleMatrix.html">ComplexDoubleMatrix</a> in the package
+ org.jblas.la which represent real and complex matrices in single and
+ double precision.</li>
+</ul>
+<ul>
+ <li>Higher-level routines for solving equations, or computing
+ eigenvalues are grouped in classes like <a href="org/jblas/la/Eigen.html">Eigen</a>, <a href="org/jblas/la/Solve.html">Solve</a>, or <a href="org/jblas/la/Geometry.html">Geometry</a>.</li>
+</ul>
+<ul>
+ <li>To construct a new matrix, you can either use the constructor, or
+ one of the factory methods <code>ones</code> (constructs a matrix of all ones),
+ <code>zeros</code>, <code>rand</code> (entries uniformly distributed between 0 and 1),
+ <code>randn</code> (entries normally distributed), <code>eye</code> (unit matrix), <code>diag</code>
+ (matrix with given diagonal). Dimensions are specified in the order
+ “row”, “column”. The number of columns defaults to 1 if omitted
+ (meaning that you construct a row vector, if you supply just one
+ dimension).</li>
+</ul>
+<ul>
+ <li>To access elements, you use <code>put</code> and <code>get</code>. Methods also exist for
+ reading or writing a whole column, row, or submatrix.</li>
+</ul>
+<ul>
+ <li>There exist only two-dimensional matrices. Vectors are matrices
+ whose columns or rows are 0. This has turned out to be much more
+ convenient thatn having separated classes.</li>
+</ul>
+<ul>
+ <li>Every math operator maps to a short mnemonic name. For example, +
+ becomes <code>add</code>, – becomes <code>sub</code>, * becomes <code>mul</code>, / becomes <code>div</code>,
+ and so on.</li>
+</ul>
+<ul>
+ <li>Often, you can pass a double or float value, or a matric with only
+ one element as the argument to a method, for example, to add the
+ same value to all elements of the matrix.</li>
+</ul>
+<ul>
+ <li><code>mul</code> is element-wise multiplication. Matrix-matrix multiplication
+ is called <code>mmul</code>.</li>
+</ul>
+<ul>
+ <li>Often, you can add an “i” to a method to have it work “in-place”. For
+ example, <code>addi</code> is like <code>+=</code>.</li>
+</ul>
+<p>What is missing right now:</p>
+<ul>
+ <li>Right now, the four classes more or less exist next to each other,
+ with no abstract superclass. This makes the classes pretty
+ straightforward, but the downside is that you cannot have a function
+ which works with any kind of matrices.</li>
+</ul>
+<ul>
+ <li>No support for sparse matrices.</li>
+</ul>
+<ul>
+ <li>Not all of <span class="caps">LAPACK</span> is covered, only things I’m using myself. In
+ principle, there is little overhead in adding further functions as
+ the generation of wrappers is automatic, but I’d rather include a
+ function from <span class="caps">LAPACK</span> only after I’m sure it does what it’s supposed
+ to do. In other words, I’ll happily add anything somebody needs as
+ long as he can check whether the method works as it should.</li>
+</ul>
+<ul>
+ <li>Build only works for Windows (XP) with Cygwin and Linux. Mac OS X
+ would be most welcome, but I don’t have access to such a machine.</li>
+</ul>
+<ul>
+ <li>jblas uses double and float arrays to store the matrix. Whenever you
+ call a native function, the array is first copied. This means that
+ it doesn’t make much sense to call a native routine if its
+ computation is linear in the size of the data, but this includes
+ most of <span class="caps">BLAS</span> Level 1 and Level 2. jblas therefore uses Java
+ implementation for things like vector addition, or even
+ matrix-vector multiplication and is therefore not as fast as native
+ <span class="caps">BLAS</span>. Currently, I’m contemplating some caching schemes to improve
+ performance here.</li>
+</ul></body></html>
\ No newline at end of file
diff --git a/src/overview.textile b/src/overview.textile
new file mode 100644
index 0000000..500191b
--- /dev/null
+++ b/src/overview.textile
@@ -0,0 +1,80 @@
+h1. jblas - Linear Algebra for Java
+
+<em>If you are really impatient, I'd suggest you read the Classes
+Overview below and otherwise stick to the API Documentation for the
+classes like DoubleMatrix.</em>
+
+The main goals of jblas were to provide very high performance, close
+to what you get from state-of-the-art BLAS and LAPACK libraries, and
+easy of use, which means that in the ideal case, you can just
+mechanically translate a matrix expression from formulas to Java
+code.
+
+In all brevity, here is what you need to know to get started:
+
+* There exist four classes: FloatMatrix, DoubleMatrix,
+ ComplexFloatMatrix and ComplexDoubleMatrix in the package
+ org.jblas.la which represent real and complex matrices in single and
+ double precision.
+
+* Higher-level routines for solving equations, or computing
+ eigenvalues are grouped in classes like Eigen, Solve, or Geometry.
+
+* To construct a new matrix, you can either use the constructor, or
+ one of the factory methods @ones@ (constructs a matrix of all ones),
+ @zeros@, @rand@ (entries uniformly distributed between 0 and 1),
+ @randn@ (entries normally distributed), @eye@ (unit matrix), @diag@
+ (matrix with given diagonal). Dimensions are specified in the order
+ "row", "column". The number of columns defaults to 1 if omitted
+ (meaning that you construct a row vector, if you supply just one
+ dimension).
+
+* To access elements, you use @put@ and @get at . Methods also exist for
+ reading or writing a whole column, row, or submatrix.
+
+* There exist only two-dimensional matrices. Vectors are matrices
+ whose columns or rows are 0. This has turned out to be much more
+ convenient thatn having separated classes.
+
+* Every math operator maps to a short mnemonic name. For example, +
+ becomes @add@, - becomes @sub@, * becomes @mul@, / becomes @div@,
+ and so on.
+
+* Often, you can pass a double or float value, or a matric with only
+ one element as the argument to a method, for example, to add the
+ same value to all elements of the matrix.
+
+* @mul@ is element-wise multiplication. Matrix-matrix multiplication
+ is called @mmul at .
+
+* Often, you can add an "i" to a method to have it work "in-place". For
+ example, @addi@ is like @+=@.
+
+What is missing right now:
+
+* Right now, the four classes more or less exist next to each other,
+ with no abstract superclass. This makes the classes pretty
+ straightforward, but the downside is that you cannot have a function
+ which works with any kind of matrices.
+
+* No support for sparse matrices.
+
+* Not all of LAPACK is covered, only things I'm using myself. In
+ principle, there is little overhead in adding further functions as
+ the generation of wrappers is automatic, but I'd rather include a
+ function from LAPACK only after I'm sure it does what it's supposed
+ to do. In other words, I'll happily add anything somebody needs as
+ long as he can check whether the method works as it should.
+
+* Build only works for Windows (XP) with Cygwin and Linux. Mac OS X
+ would be most welcome, but I don't have access to such a machine.
+
+* jblas uses double and float arrays to store the matrix. Whenever you
+ call a native function, the array is first copied. This means that
+ it doesn't make much sense to call a native routine if its
+ computation is linear in the size of the data, but this includes
+ most of BLAS Level 1 and Level 2. jblas therefore uses Java
+ implementation for things like vector addition, or even
+ matrix-vector multiplication and is therefore not as fast as native
+ BLAS. Currently, I'm contemplating some caching schemes to improve
+ performance here.
\ No newline at end of file
diff --git a/test/org/jblas/core/Dynamic.java b/test/org/jblas/core/Dynamic.java
new file mode 100644
index 0000000..76feaf6
--- /dev/null
+++ b/test/org/jblas/core/Dynamic.java
@@ -0,0 +1,49 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.core;
+
+public class Dynamic {
+ public static native void hello();
+
+ public static void main(String[] args) {
+ System.out.println("trying to load library");
+ System.loadLibrary("Dynamic");
+ System.out.println("done");
+ hello();
+ System.out.println("done calling hello");
+ }
+}
diff --git a/test/org/jblas/core/TestComplexFloat.java b/test/org/jblas/core/TestComplexFloat.java
new file mode 100644
index 0000000..cc19d09
--- /dev/null
+++ b/test/org/jblas/core/TestComplexFloat.java
@@ -0,0 +1,80 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.core;
+
+import org.jblas.core.ComplexFloat;
+import junit.framework.TestCase;
+
+public class TestComplexFloat extends TestCase {
+ public TestComplexFloat() {
+ }
+
+ private ComplexFloat a, b;
+
+ public void setUp() {
+ a = new ComplexFloat(1, 2);
+ b = new ComplexFloat(3, 4);
+ }
+
+ public void testAdd() {
+ ComplexFloat c = a.add(b);
+
+ assertEquals(4.0f, c.real());
+ assertEquals(6.0f, c.imag());
+ }
+
+ public void testMul() {
+ ComplexFloat c = a.mul(b);
+
+ assertEquals(-5.0f, c.real());
+ assertEquals(10.0f, c.imag());
+ }
+
+ public void testMulAndDiv() {
+ ComplexFloat d = a.mul(b).div(b);
+
+ assertEquals(new ComplexFloat(1.0f, 2.0f), d);
+
+ d = a.mul(b).mul(b.inv());
+
+ assertEquals(new ComplexFloat(1.0f, 2.0f), d);
+ }
+
+ public void testDivByZero() {
+ a.div(new ComplexFloat(0.0f, 0.0f));
+ }
+}
diff --git a/test/org/jblas/la/BenchmarkAccess.java b/test/org/jblas/la/BenchmarkAccess.java
new file mode 100644
index 0000000..df2b985
--- /dev/null
+++ b/test/org/jblas/la/BenchmarkAccess.java
@@ -0,0 +1,89 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import junit.framework.TestCase;
+
+import static org.jblas.la.TicToc.*;
+
+public class BenchmarkAccess extends TestCase {
+ public void testArrayVsDirectBuffer() {
+ System.out.println("Testing array access versus direct buffer access");
+
+ int SIZE = 100;
+ int ITERS = 10000000;
+ DoubleMatrix ma = new DoubleMatrix(1, SIZE);
+ double[] aa = new double[SIZE];
+ DoubleMatrix mb = new DoubleMatrix(1, SIZE);
+ double[] ab = new double[SIZE];
+
+ tic("double[]:");
+ for (int j = 0; j < ITERS; j++)
+ for (int i = 0; i < SIZE; i++) {
+ aa[i] = ab[i];
+ }
+ toc();
+
+ /*tic("DoubleBuffer.put()");
+ for (int j = 0; j < ITERS; j++)
+ for (int i = 0; i < SIZE; i++) {
+ mb.data.put(i, ma.data.get(i));
+ }
+ toc();*/
+
+ tic("DoubleMatrix.put()");
+ for (int j = 0; j < ITERS; j++)
+ for (int i = 0; i < SIZE; i++) {
+ mb.put(i, ma.get(i));
+ }
+ toc();
+
+ tic("DoubleMatrix.put() (two-dim)");
+ for (int j = 0; j < ITERS; j++)
+ for (int i = 0; i < SIZE; i++) {
+ mb.put(0, i, ma.get(0, i));
+ }
+ toc();
+
+ tic("Blas.dcopy");
+ for (int j = 0; j < ITERS; j++)
+ Blas.dcopy(SIZE, mb.data, 0, 1, ma.data, 0, 1);
+ toc();
+
+ System.out.println("Done");
+ }
+}
diff --git a/test/org/jblas/la/BenchmarkComplex.java b/test/org/jblas/la/BenchmarkComplex.java
new file mode 100644
index 0000000..5958452
--- /dev/null
+++ b/test/org/jblas/la/BenchmarkComplex.java
@@ -0,0 +1,79 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.ComplexDoubleMatrix;
+import junit.framework.TestCase;
+import static org.jblas.la.TicToc.*;
+
+public class BenchmarkComplex extends TestCase {
+ public void testMul() {
+ int ITERS = 50000;
+ int SIZE = 100;
+ ComplexDoubleMatrix A = new ComplexDoubleMatrix(SIZE, SIZE);
+ ComplexDoubleMatrix B = new ComplexDoubleMatrix(SIZE, SIZE);
+ ComplexDoubleMatrix C = new ComplexDoubleMatrix(SIZE, SIZE);
+
+ tic("Multiplying two matrices %d times", ITERS);
+ for (int i = 0; i < ITERS; i++)
+ A.muli(B, C);
+ printMflops(6L*SIZE*SIZE*ITERS, toc());
+
+ tic("Doing it with temp variables");
+ for (int i = 0; i < ITERS; i++)
+ for (int j = 0; j < A.length; j++)
+ C.put(j, A.get(j).mul(B.get(j)));
+ printMflops(6L*SIZE*SIZE*ITERS, toc());
+
+ tic("Doing it by hand");
+ for (int i = 0; i < ITERS; i++)
+ for (int j = 0; j < 2*A.length; j+=2) {
+ double ar = A.data[j], ai = A.data[j+1];
+ double br = B.data[j], bi = B.data[j+1];
+ double cr = ar * br - ai * bi;
+ double ci = ar * bi + ai * br;
+ C.data[j] = cr;
+ C.data[j+1] = ci;
+ }
+ printMflops(6L*SIZE*SIZE*ITERS, toc());
+ }
+
+ private void printMflops(long ops, double time) {
+ System.out.printf(" [INFO] %.3f MFLOPS (%.1f million operations)\n", ops / time / 1e6d, ops / 1e6d);
+ }
+
+}
diff --git a/test/org/jblas/la/BenchmarkElementwise.java b/test/org/jblas/la/BenchmarkElementwise.java
new file mode 100644
index 0000000..283056d
--- /dev/null
+++ b/test/org/jblas/la/BenchmarkElementwise.java
@@ -0,0 +1,99 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import junit.framework.TestCase;
+import static org.jblas.la.TicToc.*;
+import static org.jblas.la.DoubleMatrix.*;
+
+public class BenchmarkElementwise extends TestCase {
+ public void testMuli() {
+ int SIZE = 1000;
+ int ITERS = 1000000;
+ DoubleMatrix x = rand(SIZE);
+ DoubleMatrix y = rand(SIZE);
+ DoubleMatrix z = zeros(SIZE);
+
+ tic("muli():");
+ for (int i = 0; i < ITERS; i++)
+ x.muli(y, z);
+ toc();
+
+ double xa[]= new double[SIZE];
+ double ya[]= new double[SIZE];
+ double za[]= new double[SIZE];
+
+ tic("muli (array):");
+ for (int i = 0; i < ITERS; i++)
+ for (int j = 0; j < SIZE; j++)
+ za[j] = xa[j] * ya[j];
+ toc();
+
+ /*tic("muli (double buffer:");
+ for (int i = 0; i < ITERS; i++)
+ for (int j = 0; j < SIZE; j++)
+ z.data.put(j, x.data.get(j) * y.data.get(j));
+ toc();*/
+
+ tic("divi():");
+ for (int i = 0; i < ITERS/10; i++)
+ x.divi(y, z);
+ toc();
+
+ tic("addi():");
+ for (int i = 0; i < ITERS; i++)
+ x.addi(y, z);
+ toc();
+
+ tic("addi() array:");
+ for (int i = 0; i < ITERS; i++)
+ for (int j = 0; j < SIZE; j++)
+ za[j] = xa[j] + ya[j];
+ toc();
+
+ /*tic("addi() doublebuffer:");
+ for (int i = 0; i < ITERS; i++)
+ for (int j = 0; j < SIZE; j++)
+ z.data.put(j, x.data.get(j) + y.data.get(j));
+ toc();*/
+
+ tic("subi():");
+ for (int i = 0; i < ITERS; i++)
+ x.subi(y, z);
+ toc();
+ }
+}
diff --git a/test/org/jblas/la/BenchmarkMatrix.java b/test/org/jblas/la/BenchmarkMatrix.java
new file mode 100644
index 0000000..0676f49
--- /dev/null
+++ b/test/org/jblas/la/BenchmarkMatrix.java
@@ -0,0 +1,164 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la;
+
+import org.jblas.la.SimpleBlas;
+import org.jblas.la.DoubleMatrix;
+import org.jblas.la.FloatMatrix;
+import junit.framework.TestCase;
+
+import static org.jblas.la.TicToc.*;
+
+/**
+ *
+ * @author mikio
+ */
+public class BenchmarkMatrix extends TestCase {
+
+ private void printMflops(long ops, double time) {
+ System.out.printf(" [INFO] %.3f MFLOPS (%.1f million operations)\n", ops / time / 1e6d, ops / 1e6d);
+ }
+
+ public void setUp() {
+ }
+
+ public void testBenchmarkMMulDouble() {
+ final int n = 1000;
+ DoubleMatrix x, y, z;
+ x = DoubleMatrix.randn(n, n);
+ y = DoubleMatrix.randn(n, n);
+ z = DoubleMatrix.randn(n, n);
+
+ double time;
+
+ tic("Multiplying DOUBLE matrices of size %d", n);
+ SimpleBlas.gemm(1.0, x, y, 0.0, z);
+ time = toc();
+
+ long ops = 2L*n*n*n;
+ printMflops(ops, time);
+ }
+
+ public void testBenchmarkMMulFloat() {
+ final int n = 1000;
+ FloatMatrix x = FloatMatrix.randn(n, n);
+ FloatMatrix y = FloatMatrix.randn(n, n);
+ FloatMatrix z = FloatMatrix.randn(n, n);
+ double time;
+
+ tic("Multiplying FLOAT matrices of size %d", n);
+ SimpleBlas.gemm(1.0f, x, y, 0.0f, z);
+ printMflops(2L*n*n*n, toc());
+ }
+
+ public void testBenchmarkAxpyAndDot() {
+ final int n = 10000;
+ final int ITERS = 10000;
+ DoubleMatrix x = DoubleMatrix.randn(n);
+ DoubleMatrix y = DoubleMatrix.randn(n);
+
+ tic("Doing axpy with %d elements %d times", n, ITERS);
+ for (int i = 0; i < ITERS; i++)
+ SimpleBlas.axpy(1.0, x, y);
+ printMflops(n * ITERS, toc());
+
+ tic("Doing dot with %d elements %d times", n, ITERS);
+ for (int i = 0; i < ITERS; i++)
+ SimpleBlas.dot(x, y);
+ printMflops(n * ITERS, toc());
+ }
+
+ public void testBenchmarkAxpyAndDotFloat() {
+ final int n = 10000;
+ final int ITERS = 10000;
+ FloatMatrix x = FloatMatrix.randn(n);
+ FloatMatrix y = FloatMatrix.randn(n);
+
+ tic("Doing FLOAT axpy with %d elements %d times", n, ITERS);
+ for (int i = 0; i < ITERS; i++)
+ SimpleBlas.axpy(1.0f, x, y);
+ printMflops(n * ITERS, toc());
+
+ tic("Doing FLOAT dot with %d elements %d times", n, ITERS);
+ for (int i = 0; i < ITERS; i++)
+ SimpleBlas.dot(x, y);
+ printMflops(n * ITERS, toc());
+ }
+
+ public void testBenchmarkGemvDouble() {
+ final int m = 1000;
+ final int n = 2000;
+ final int ITERS = 100;
+ DoubleMatrix x = DoubleMatrix.randn(m, n);
+ DoubleMatrix y = DoubleMatrix.randn(n, 1);
+ DoubleMatrix z = DoubleMatrix.randn(m, 1);
+
+ tic("Doing DOUBLE Gemv with matrices of size %d * %d for %d times", m, n, ITERS);
+ for (int i = 0; i < ITERS; i++)
+ SimpleBlas.gemv(1.0, x, y, 0.0, z);
+ printMflops(2l*m*n*ITERS, toc());
+
+ tic("Doing DOUBLE Gemm with matrices of size %d * %d for %d times", m, n, ITERS);
+ for (int i = 0; i < ITERS; i++)
+ SimpleBlas.gemm(1.0, x, y, 0.0, z);
+ printMflops(2l*m*n*ITERS, toc());
+ }
+
+ public void testBenchmarkGemvFloat() {
+ final int m = 1000;
+ final int n = 2000;
+ final int ITERS = 100;
+ FloatMatrix x = FloatMatrix.randn(m, n);
+ FloatMatrix y = FloatMatrix.randn(n, 1);
+ FloatMatrix z = FloatMatrix.randn(m, 1);
+
+ tic("Doing Float Gemv with matrices of size %d * %d for %d times", m, n, ITERS);
+ for (int i = 0; i < ITERS; i++)
+ SimpleBlas.gemv(1.0f, x, y, 0.0f, z);
+ printMflops(2l*m*n*ITERS, toc());
+
+ tic("Doing Float Gemm with matrices of size %d * %d for %d times", m, n, ITERS);
+ for (int i = 0; i < ITERS; i++)
+ SimpleBlas.gemm(1.0f, x, y, 0.0f, z);
+ printMflops(2l*m*n*ITERS, toc());
+ }
+}
diff --git a/test/org/jblas/la/ComplexDoubleMatrixTest.java b/test/org/jblas/la/ComplexDoubleMatrixTest.java
new file mode 100644
index 0000000..cd3a566
--- /dev/null
+++ b/test/org/jblas/la/ComplexDoubleMatrixTest.java
@@ -0,0 +1,88 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la;
+
+import org.jblas.la.DoubleMatrix;
+import org.jblas.la.ComplexDoubleMatrix;
+import org.jblas.core.ComplexDouble;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author mikio
+ */
+public class ComplexDoubleMatrixTest extends TestCase {
+
+ public ComplexDoubleMatrixTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testConstruction() {
+ ComplexDoubleMatrix A = new ComplexDoubleMatrix(3, 3);
+
+ for (int i = 0; i < A.rows; i++)
+ for (int j = 0; j < A.columns; j++)
+ A.put(i, j, new ComplexDouble(i, j));
+ System.out.printf("A = %s\n", A.toString());
+
+ System.out.println(A.mmul(A));
+
+ DoubleMatrix R = new DoubleMatrix(3, 3, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
+ A = new ComplexDoubleMatrix(R, R.transpose());
+ System.out.println(A);
+
+ assertEquals(A.real(), R);
+ assertEquals(A.imag(), R.transpose());
+ }
+}
diff --git a/test/org/jblas/la/DemoImages.java b/test/org/jblas/la/DemoImages.java
new file mode 100644
index 0000000..53f6380
--- /dev/null
+++ b/test/org/jblas/la/DemoImages.java
@@ -0,0 +1,319 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.DoubleMatrix;
+import org.jblas.la.Blas;
+import junit.framework.TestCase;
+import static org.jblas.la.TicToc.*;
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+import java.io.File;
+import java.io.IOException;
+import static org.jblas.la.MatrixFunctions.*;
+import java.util.Arrays;
+
+public class DemoImages extends TestCase {
+ private DoubleMatrix tile(DoubleMatrix x, int ix, int iy, int wx, int wy) {
+ int width = (x.rows - ix) / wx;
+ int height = (x.columns - iy) / wy;
+ DoubleMatrix result = new DoubleMatrix(width*height, wx*wy);
+ int counter = 0;
+ for (int i = 0; i < x.rows - width; i += wx)
+ for (int j = 0; j < x.columns - height; j += wy) {
+ copyRect2(result, counter++, x, wx, wy, i, j);
+ }
+ return result;
+ }
+
+ private void copyRect2(DoubleMatrix result, int counter, DoubleMatrix x, int wx, int wy, int i, int j) {
+ for (int jj = 0; jj < wx; jj++)
+ Blas.dcopy(wy, x.data, x.index(i, j + jj), 1, result.data, result.index(counter, jj * wy), result.rows);
+ }
+
+ private void copyRect(DoubleMatrix result, int counter, DoubleMatrix x, int wx, int wy, int i, int j) {
+ int[] I = range(i, i + wx - 1);
+ int[] J = range(j, j + wy - 1);
+ result.putRow(counter, x.get(I, J));
+ }
+
+ private int[] range(int a, int b) {
+ int[] result = new int[b - a + 1];
+ for (int i = 0; i <= b - a; i++)
+ result[i] = a + i;
+ return result;
+ }
+
+ private int[] range(int a, int s, int b) {
+ int[] result = new int[(b - a + (s-1)) / s];
+ for (int c = 0, i = a; c < result.length; i += s, c++)
+ result[c] = i;
+ return result;
+ }
+
+ private void print(int[] a) {
+ if (a.length == 0)
+ System.out.println("[]");
+ else {
+ System.out.print("[");
+ for (int i = 0; i < a.length - 1; i++)
+ System.out.printf("%d; ", a[i]);
+ System.out.printf("%d]\n", a[a.length - 1]);
+ }
+ }
+
+ public void testRange() {
+ System.out.println("testRange-------");
+ print(range(1,3));
+ for (int i = 1; i < 10; i++) {
+ System.out.printf("i = %d ", i);
+ print(range(1,2,i));
+ }
+ }
+
+ private DoubleMatrix[] loadImage(String name)
+ throws IOException {
+ BufferedImage image = ImageIO.read(new File(name));
+
+ DoubleMatrix[] result = new DoubleMatrix[3];
+ for (int i = 0; i < 3; i++) {
+ result[i] = new DoubleMatrix(image.getWidth(), image.getHeight());
+ }
+
+ for (int x = 0; x < image.getWidth(); x++) {
+ for (int y = 0; y < image.getHeight(); y++) {
+ int pixel = image.getRGB(x, y);
+ result[0].put(x, y, ((pixel & 0xff0000) >> 16) / 255.0 );
+ result[1].put(x, y, ((pixel & 0x00ff00) >> 8) / 255.0 );
+ result[2].put(x, y, ((pixel & 0x0000ff)) / 255.0 );
+ }
+ }
+ return result;
+ }
+
+ private int doubleToByte(double v) {
+ if (v > 1.0) v = 1.0;
+ else if(v < 0.0) v = 0.0;
+ return (int) (v * 255);
+ }
+
+ private void saveImage(String name, String formatName, DoubleMatrix image)
+ throws IOException {
+ int width = image.rows;
+ int height = image.columns;
+ BufferedImage out = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+
+ for (int x = 0; x < width; x++)
+ for (int y = 0; y < height; y++) {
+ int pixel = doubleToByte(image.get(x,y));
+ pixel |= (pixel << 16) | (pixel << 8);
+ out.setRGB(x, y, pixel);
+ }
+
+ ImageIO.write(out, formatName, new File(name));
+ }
+
+ private void saveImage(String name, String formatName, DoubleMatrix[] image)
+ throws IOException {
+ int width = image[0].rows;
+ int height = image[0].columns;
+ BufferedImage out = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+
+ for (int x = 0; x < width; x++)
+ for (int y = 0; y < height; y++) {
+ int pixel = (doubleToByte(image[0].get(x,y)) << 16) |
+ (doubleToByte(image[1].get(x,y)) << 8) |
+ (doubleToByte(image[2].get(x,y)));
+ out.setRGB(x, y, pixel);
+ }
+
+ ImageIO.write(out, formatName, new File(name));
+ }
+
+ public void testTile() {
+ //DoubleMatrix x = DoubleMatrix.randn(1000,1000);
+ DoubleMatrix x = new DoubleMatrix(2000,2000);
+ for (int i = 1; i < x.length; i++)
+ x.put(i, i);
+ //x.print();
+
+ tic("Tiling matrix");
+ DoubleMatrix t = tile(x, 0, 0, 100, 100);
+ toc();
+
+ System.out.printf("And the result has %d times %d entries\n", t.rows, t.columns);
+ //t.print();
+
+ tic("Folding");
+ DoubleMatrix out = t.mmul(DoubleMatrix.ones(t.columns));
+ toc();
+
+ //out.reshape(5, 5);
+
+ //out.print();
+
+ System.out.println("Done!");
+ }
+
+ public void testLoadWrite() {
+ try {
+ tic("Loading");
+ DoubleMatrix[] img = loadImage("/home/mikio/pics/me.jpg");
+ toc();
+ tic("Saving");
+ saveImage("/home/mikio/pics/saved_me.png", "png", img);
+ toc();
+ } catch(IOException e) {
+ System.err.println("Error reading or writing file");
+ }
+ }
+
+ public long ops;
+ public long mult_ops;
+ public long add_ops;
+ public long copy_ops;
+
+ private DoubleMatrix convolute(DoubleMatrix img, DoubleMatrix weights) {
+ DoubleMatrix result = new DoubleMatrix(img.rows - weights.columns, img.columns - weights.rows);
+ DoubleMatrix w = new DoubleMatrix(img.rows, weights.columns);
+
+ ops = 0;
+
+ for (int i = 0; i < img.columns - weights.rows; i++) {
+ // compute all filter for all columns
+ Blas.dgemm('N', 'N', img.rows, weights.rows, weights.columns,
+ 1.0, img.data, img.index(0, i), img.rows,
+ weights.data, 0, weights.rows,
+ 0.0, w.data, 0, w.rows);
+ ops += 2*(long)img.rows * weights.rows * weights.columns;
+
+ // collect results
+ // add rows of length w.rows - w.columns from j, j to first row.
+ for (int j = 1; j < w.columns; j++) {
+ Blas.daxpy(w.rows - w.columns, 1.0, w.data, img.index(j, j), 1, w.data, 0, 1);
+ ops += w.rows - w.columns;
+ }
+ // copy the result back to the output vector.
+ Blas.dcopy(w.rows - w.columns, w.data, 0, 1, result.data, result.index(0, i), 1);
+ }
+ return result;
+ }
+
+ private DoubleMatrix convoluteNaive(DoubleMatrix img, DoubleMatrix weights) {
+ int width = weights.rows;
+ int height = weights.columns;
+ DoubleMatrix result = new DoubleMatrix(img.rows - width, img.columns - height);
+ for (int i = 0; i < img.rows - width; i++)
+ for (int j = 0; j < img.columns - height; j++) {
+ double sum = 0.0;
+ for (int l = 0; l < height; l++) {
+ for (int k = 0; k < width; k++) {
+ sum += img.get(i + k, j + l) * weights.get(k, l);
+ }
+ }
+ result.put(i, j, sum);
+ }
+ ops += 2 * (long)(img.rows - width) * (img.columns - height) * height * width;
+ return result;
+ }
+
+ private double ringMask(double x, double y) {
+ double d = sqrt(x*x + y*y);
+ if (d < 0.0 || d >= 10.0)
+ return 0.0;
+ else
+ return 1.0;
+ }
+
+ private double mexicanHatMask(double x, double y) {
+ double d = x*x + y*y;
+ double sigma = 2;
+ return 1/(sqrt(2*Math.PI)*sigma*sigma*sigma) * (1 - d/(sigma*sigma)) *
+ exp(- d / (2 * sigma*sigma));
+ }
+
+ private DoubleMatrix makeMask(int[] x, int[] y) {
+ DoubleMatrix result = new DoubleMatrix(x.length, y.length);
+
+ for (int i = 0; i < x.length; i++)
+ for (int j = 0; j < y.length; j++)
+ result.put(i, j, mexicanHatMask(x[i], y[j]));
+ return result;
+ }
+
+ public void testConvolute() {
+ try {
+ DoubleMatrix[] img = loadImage("/home/mikio/pics/img.jpg");
+
+ tic("Converting to grayscale");
+ DoubleMatrix scaledRed = img[0].mul(0.4);
+ DoubleMatrix scaledGreen = img[1].mul(0.4);
+ DoubleMatrix scaledBlue = img[2].mul(0.2);
+ DoubleMatrix gray = scaledRed.addi(scaledGreen).addi(scaledBlue);
+ toc();
+
+ DoubleMatrix weights = makeMask(range(-20, 20), range(-20, 20));
+ //DoubleMatrix weights = DoubleMatrix.randn(51,51);
+ tic("Convoluting");
+ DoubleMatrix cgray = convolute(gray, weights);
+ double time = toc();
+ cgray.addi(0.5);
+ cgray.divi(abs(cgray).max());
+
+ System.out.printf("[INFO] weight size = %d\n", weights.length);
+ System.out.printf("[INFO] total ops = %.3fM (%.3f MFLOPS)\n", ops / 1000000d, ops / 1000000d / time);
+
+ saveImage("/home/mikio/pics/saved_img.jpg", "jpg", cgray);
+ } catch(IOException e) {
+ System.err.println("Error reading or writing file");
+ }
+ }
+
+ int countHowMany(int s, int I) {
+ int counter = 0;
+ for (int i = 0; i < I; i += s)
+ counter++;
+ return counter;
+ }
+
+ public void testHowMany() {
+ /*for (int s = 1; s < 5; s++)
+ for (int i = 0; i < 20; i++)
+ System.out.printf("0..%d..%d => %d (vs. %d)\n", s, i, countHowMany(s, i), (i - 0 + (s-1)) / s);
+ */
+ }
+}
diff --git a/test/org/jblas/la/EigenTest.java b/test/org/jblas/la/EigenTest.java
new file mode 100644
index 0000000..446af1a
--- /dev/null
+++ b/test/org/jblas/la/EigenTest.java
@@ -0,0 +1,79 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.jblas.la;
+
+import org.jblas.la.Eigen;
+import org.jblas.la.DoubleMatrix;
+import org.jblas.la.ComplexDoubleMatrix;
+import junit.framework.TestCase;
+import static org.jblas.la.TicToc.*;
+
+/**
+ *
+ * @author mikio
+ */
+public class EigenTest extends TestCase {
+
+ public EigenTest(String testName) {
+ super(testName);
+ }
+
+ public void testEigenvalues() {
+ DoubleMatrix A = new DoubleMatrix(2, 2, 3.0, -3.0, 1.0, 1.0);
+
+ ComplexDoubleMatrix E = Eigen.eigenvalues(A);
+
+ System.out.printf("E = %s\n", E.toString());
+
+ ComplexDoubleMatrix[] EV = Eigen.eigenvectors(A);
+
+ System.out.printf("values = %s\n", EV[1].toString());
+ System.out.printf("vectors = %s\n", EV[0].toString());
+ }
+
+ public void testBenchmarkEigenvalues() {
+ tic("Computing eigenvalues of random 1000*1000 matrix");
+ ComplexDoubleMatrix EV = Eigen.eigenvalues(DoubleMatrix.randn(500,500));
+ toc();
+
+ System.out.printf("EV = %s\n", EV.toString());
+ }
+}
diff --git a/test/org/jblas/la/SimpleBlasTest.java b/test/org/jblas/la/SimpleBlasTest.java
new file mode 100644
index 0000000..d366d66
--- /dev/null
+++ b/test/org/jblas/la/SimpleBlasTest.java
@@ -0,0 +1,77 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.la;
+
+import org.jblas.la.SimpleBlas;
+import org.jblas.la.DoubleMatrix;
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author mikio
+ */
+public class SimpleBlasTest extends TestCase {
+
+ public SimpleBlasTest(String testName) {
+ super(testName);
+ }
+
+ public void testGeev() {
+ DoubleMatrix A = new DoubleMatrix(2, 2, 3.0, -3.0, 1.0, 1.0);
+ DoubleMatrix WR = new DoubleMatrix(2);
+ DoubleMatrix WI = new DoubleMatrix(2);
+ DoubleMatrix VR = new DoubleMatrix(2,2);
+ DoubleMatrix VL = new DoubleMatrix(2,2);
+
+ SimpleBlas.geev('V', 'N', A, WR, WI, VR, VL);
+
+ assertEquals(new DoubleMatrix(2, 1, 2.0, 2.0), WR);
+ assertEquals(new DoubleMatrix(2, 1, Math.sqrt(2.0), -Math.sqrt(2.0)), WI);
+
+ System.out.printf("WR = %s\n", WR.toString());
+ System.out.printf("WI = %s\n", WI.toString());
+ System.out.printf("VR = %s\n", VR.toString());
+ System.out.printf("VL = %s\n", VL.toString());
+ System.out.printf("A = %s\n", A.toString());
+
+ }
+}
diff --git a/test/org/jblas/la/TestBlasDouble.java b/test/org/jblas/la/TestBlasDouble.java
new file mode 100644
index 0000000..690eba2
--- /dev/null
+++ b/test/org/jblas/la/TestBlasDouble.java
@@ -0,0 +1,183 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import junit.framework.TestCase;
+
+import static org.jblas.la.MatrixFunctions.*;
+
+public class TestBlasDouble extends TestCase {
+
+ /** test sum of absolute values */
+ public void testAsum() {
+ double[] a = new double[]{1.0, 2.0, 3.0, 4.0};
+
+ assertEquals(10.0, Blas.dasum(4, a, 0, 1));
+ assertEquals(4.0, Blas.dasum(2, a, 0, 2));
+ assertEquals(5.0, Blas.dasum(2, a, 1, 1));
+ }
+
+ /** test scalar product */
+ public void testDot() {
+ double[] a = new double[] { 1.0, 2.0, 3.0, 4.0 };
+ double[] b = new double[] { 4.0, 5.0, 6.0, 7.0 };
+
+ assertEquals(32.0, Blas.ddot(3, a, 0, 1, b, 0, 1));
+ assertEquals(22.0, Blas.ddot(2, a, 0, 2, b, 0, 2));
+ assertEquals(5.0 + 12.0 + 21.0, Blas.ddot(3, a, 0, 1, b, 1, 1));
+ }
+
+ public void testSwap() {
+ double[] a = new double[] { 1.0, 2.0, 3.0, 4.0 };
+ double[] b = new double[] { 4.0, 5.0, 6.0, 7.0 };
+ double[] c = new double[] { 1.0, 2.0, 3.0, 4.0 };
+ double[] d = new double[] { 4.0, 5.0, 6.0, 7.0 };
+
+ System.out.println("dswap");
+ Blas.dswap(4, a, 0, 1, b, 0, 1);
+ assertTrue(arraysEqual(a, d));
+ assertTrue(arraysEqual(b, c));
+
+ System.out.println("dswap same");
+ Blas.dswap(2, a, 0, 2, a, 1, 2);
+ assertTrue(arraysEqual(a, 5.0, 4.0, 7.0, 6.0));
+ }
+
+ /* test vector addition */
+ public void testAxpy() {
+ double[] x = new double[] { 1.0, 2.0, 3.0, 4.0 };
+ double[] y = new double[] { 0.0, 0.0, 0.0, 0.0 };
+
+ Blas.daxpy(4, 2.0, x, 0, 1, y, 0, 1);
+
+ for(int i = 0; i < 4; i++)
+ assertEquals(2*x[i], y[i]);
+ }
+
+ /* test matric-vector multiplication */
+ public void testGemv() {
+ double[] A = new double[] { 1.0, 2.0, 3.0,
+ 4.0, 5.0, 6.0,
+ 7.0, 8.0, 9.0 };
+
+ double[] x = new double[] {1.0, 3.0, 7.0 };
+ double[] y = new double[] { 0.0, 0.0, 0.0 };
+
+ Blas.dgemv('N', 3, 3, 1.0, A, 0, 3, x, 0, 1, 0.0, y, 0, 1);
+
+ //printMatrix(3, 3, A);
+ //printMatrix(3, 1, x);
+ //printMatrix(3, 1, y);
+
+ assertTrue(arraysEqual(y, 62.0, 73.0, 84.0));
+
+ Blas.dgemv('T', 3, 3, 1.0, A, 0, 3, x, 0, 1, 0.5, y, 0, 1);
+
+ //printMatrix(3, 1, y);
+ assertTrue(arraysEqual(y, 59.0, 97.5, 136.0));
+ }
+
+ /** Compare double buffer against an array of doubles */
+ private boolean arraysEqual(double[] a, double... b) {
+ if (a.length != b.length)
+ return false;
+ else {
+ double diff = 0.0;
+ for (int i = 0; i < b.length; i++)
+ diff += abs(a[i] - b[i]);
+ return diff < 1e-6;
+ }
+ }
+
+ public static void main(String[] args) {
+ TestBlasDouble t = new TestBlasDouble();
+
+ t.testAsum();
+ }
+
+ public static void testSolve() {
+ DoubleMatrix A = new DoubleMatrix(3, 3, 3.0, 5.0, 6.0, 1.0, 0.0, 0.0, 2.0, 4.0, 0.0);
+ DoubleMatrix X = new DoubleMatrix(3, 1, 1.0, 2.0, 3.0);
+ int[] p = new int[3];
+ SimpleBlas.gesv(A, p, X);
+ A.print();
+ X.print();
+ // De-shuffle X
+ for (int i = 2; i >= 0; i--) {
+ int perm = p[i] - 1;
+ double t = X.get(i); X.put(i, X.get(perm)); X.put(perm, t);
+ }
+ System.out.println();
+ X.print();
+ }
+
+ public static void testSymmetricSolve() {
+ System.out.println("--- Symmetric solve");
+ DoubleMatrix A = new DoubleMatrix(3, 3, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
+ DoubleMatrix x = new DoubleMatrix(3, 1, 1.0, 2.0, 3.0);
+ int[] p = new int[3];
+ SimpleBlas.sysv('U', A, p, x);
+ A.print();
+ x.print();
+ }
+
+ public static void testSYEV() {
+ System.out.println("--- Symmetric eigenvalues");
+ int n = 10;
+ DoubleMatrix x = DoubleMatrix.randn(n).sort();
+
+ //DoubleMatrix A = new DoubleMatrix(new double[][] {{1.0, 0.5, 0.1}, {0.5, 1.0, 0.5}, {0.1, 0.5, 1.0}});
+ DoubleMatrix A = expi(Geometry.pairwiseSquaredDistances(x, x).muli(-2.0));
+ DoubleMatrix w = new DoubleMatrix(n);
+
+ DoubleMatrix B = A.dup();
+ System.out.println("Computing eigenvalues with SYEV");
+ SimpleBlas.syev('V', 'U', B, w);
+ System.out.println("Eigenvalues: ");
+ w.print();
+ System.out.println("Eigenvectors: ");
+ B.print();
+
+ B = A.dup();
+ System.out.println("Computing eigenvalues with SYEVD");
+ SimpleBlas.syevd('V', 'U', B, w);
+ System.out.println("Eigenvalues: ");
+ w.print();
+ System.out.println("Eigenvectors: ");
+ B.print();
+ }
+}
diff --git a/test/org/jblas/la/TestBlasDoubleComplex.java b/test/org/jblas/la/TestBlasDoubleComplex.java
new file mode 100644
index 0000000..d3371ed
--- /dev/null
+++ b/test/org/jblas/la/TestBlasDoubleComplex.java
@@ -0,0 +1,63 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import junit.framework.TestCase;
+
+import org.jblas.core.ComplexDouble;
+
+public class TestBlasDoubleComplex extends TestCase {
+
+ public void testDotc() {
+ double[] a = new double[] { 1.0, 1.0, 2.0, 0.0, 3.0, 0.0 };
+
+ ComplexDouble c = Blas.zdotu(3, a, 0, 1, a, 0, 1);
+ System.out.println(c);
+ }
+
+ public void testAxpy() {
+ double[] x = new double[] { 0.0, -1.0 };
+ double[] y = new double[] { 0.0, 1.0 };
+ ComplexDouble a = new ComplexDouble(0.0, 1.0);
+
+ Blas.zdscal(1, 2.0, x, 0, 1);
+ assertEquals(new ComplexDouble(0.0, -2.0), new ComplexDouble(x[0], x[1]));
+
+ Blas.zaxpy(1, a, x, 0, 1, y, 0, 1);
+ assertEquals(new ComplexDouble(2.0, 1.0), new ComplexDouble(y[0], y[1]));
+ }
+}
diff --git a/test/org/jblas/la/TestBlasFloat.java b/test/org/jblas/la/TestBlasFloat.java
new file mode 100644
index 0000000..5a60944
--- /dev/null
+++ b/test/org/jblas/la/TestBlasFloat.java
@@ -0,0 +1,183 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import junit.framework.TestCase;
+
+import static org.jblas.la.MatrixFunctions.*;
+
+public class TestBlasFloat extends TestCase {
+
+ /** test sum of absolute values */
+ public void testAsum() {
+ float[] a = new float[]{1.0f, 2.0f, 3.0f, 4.0f};
+
+ assertEquals(10.0f, Blas.sasum(4, a, 0, 1));
+ assertEquals(4.0f, Blas.sasum(2, a, 0, 2));
+ assertEquals(5.0f, Blas.sasum(2, a, 1, 1));
+ }
+
+ /** test scalar product */
+ public void testDot() {
+ float[] a = new float[] { 1.0f, 2.0f, 3.0f, 4.0f };
+ float[] b = new float[] { 4.0f, 5.0f, 6.0f, 7.0f };
+
+ assertEquals(32.0f, Blas.sdot(3, a, 0, 1, b, 0, 1));
+ assertEquals(22.0f, Blas.sdot(2, a, 0, 2, b, 0, 2));
+ assertEquals(5.0f + 12.0f + 21.0f, Blas.sdot(3, a, 0, 1, b, 1, 1));
+ }
+
+ public void testSwap() {
+ float[] a = new float[] { 1.0f, 2.0f, 3.0f, 4.0f };
+ float[] b = new float[] { 4.0f, 5.0f, 6.0f, 7.0f };
+ float[] c = new float[] { 1.0f, 2.0f, 3.0f, 4.0f };
+ float[] d = new float[] { 4.0f, 5.0f, 6.0f, 7.0f };
+
+ System.out.println("dswap");
+ Blas.sswap(4, a, 0, 1, b, 0, 1);
+ assertTrue(arraysEqual(a, d));
+ assertTrue(arraysEqual(b, c));
+
+ System.out.println("dswap same");
+ Blas.sswap(2, a, 0, 2, a, 1, 2);
+ assertTrue(arraysEqual(a, 5.0f, 4.0f, 7.0f, 6.0f));
+ }
+
+ /* test vector addition */
+ public void testAxpy() {
+ float[] x = new float[] { 1.0f, 2.0f, 3.0f, 4.0f };
+ float[] y = new float[] { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ Blas.saxpy(4, 2.0f, x, 0, 1, y, 0, 1);
+
+ for(int i = 0; i < 4; i++)
+ assertEquals(2*x[i], y[i]);
+ }
+
+ /* test matric-vector multiplication */
+ public void testGemv() {
+ float[] A = new float[] { 1.0f, 2.0f, 3.0f,
+ 4.0f, 5.0f, 6.0f,
+ 7.0f, 8.0f, 9.0f };
+
+ float[] x = new float[] {1.0f, 3.0f, 7.0f };
+ float[] y = new float[] { 0.0f, 0.0f, 0.0f };
+
+ Blas.sgemv('N', 3, 3, 1.0f, A, 0, 3, x, 0, 1, 0.0f, y, 0, 1);
+
+ //printMatrix(3, 3, A);
+ //printMatrix(3, 1, x);
+ //printMatrix(3, 1, y);
+
+ assertTrue(arraysEqual(y, 62.0f, 73.0f, 84.0f));
+
+ Blas.sgemv('T', 3, 3, 1.0f, A, 0, 3, x, 0, 1, 0.5f, y, 0, 1);
+
+ //printMatrix(3, 1, y);
+ assertTrue(arraysEqual(y, 59.0f, 97.5f, 136.0f));
+ }
+
+ /** Compare float buffer against an array of floats */
+ private boolean arraysEqual(float[] a, float... b) {
+ if (a.length != b.length)
+ return false;
+ else {
+ float diff = 0.0f;
+ for (int i = 0; i < b.length; i++)
+ diff += abs(a[i] - b[i]);
+ return diff < 1e-6;
+ }
+ }
+
+ public static void main(String[] args) {
+ TestBlasFloat t = new TestBlasFloat();
+
+ t.testAsum();
+ }
+
+ public static void testSolve() {
+ FloatMatrix A = new FloatMatrix(3, 3, 3.0f, 5.0f, 6.0f, 1.0f, 0.0f, 0.0f, 2.0f, 4.0f, 0.0f);
+ FloatMatrix X = new FloatMatrix(3, 1, 1.0f, 2.0f, 3.0f);
+ int[] p = new int[3];
+ SimpleBlas.gesv(A, p, X);
+ A.print();
+ X.print();
+ // De-shuffle X
+ for (int i = 2; i >= 0; i--) {
+ int perm = p[i] - 1;
+ float t = X.get(i); X.put(i, X.get(perm)); X.put(perm, t);
+ }
+ System.out.println();
+ X.print();
+ }
+
+ public static void testSymmetricSolve() {
+ System.out.println("--- Symmetric solve");
+ FloatMatrix A = new FloatMatrix(3, 3, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f);
+ FloatMatrix x = new FloatMatrix(3, 1, 1.0f, 2.0f, 3.0f);
+ int[] p = new int[3];
+ SimpleBlas.sysv('U', A, p, x);
+ A.print();
+ x.print();
+ }
+
+ public static void testSYEV() {
+ System.out.println("--- Symmetric eigenvalues");
+ int n = 10;
+ FloatMatrix x = FloatMatrix.randn(n).sort();
+
+ //FloatMatrix A = new FloatMatrix(new float[][] {{1.0f, 0.5f, 0.1f}, {0.5f, 1.0f, 0.5f}, {0.1f, 0.5f, 1.0f}});
+ FloatMatrix A = expi(Geometry.pairwiseSquaredDistances(x, x).muli(-2.0f));
+ FloatMatrix w = new FloatMatrix(n);
+
+ FloatMatrix B = A.dup();
+ System.out.println("Computing eigenvalues with SYEV");
+ SimpleBlas.syev('V', 'U', B, w);
+ System.out.println("Eigenvalues: ");
+ w.print();
+ System.out.println("Eigenvectors: ");
+ B.print();
+
+ B = A.dup();
+ System.out.println("Computing eigenvalues with SYEVD");
+ SimpleBlas.syevd('V', 'U', B, w);
+ System.out.println("Eigenvalues: ");
+ w.print();
+ System.out.println("Eigenvectors: ");
+ B.print();
+ }
+}
diff --git a/test/org/jblas/la/TestDoubleMatrix.java b/test/org/jblas/la/TestDoubleMatrix.java
new file mode 100644
index 0000000..66397d3
--- /dev/null
+++ b/test/org/jblas/la/TestDoubleMatrix.java
@@ -0,0 +1,641 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.DoubleMatrix;
+import org.jblas.la.Geometry;
+import org.jblas.la.Solve;
+import junit.framework.TestCase;
+import java.util.Arrays;
+import static org.jblas.la.ranges.RangeUtils.*;
+
+public class TestDoubleMatrix extends TestCase {
+
+ DoubleMatrix A, B, C, D, E, F;
+
+ public void setUp() {
+ A = new DoubleMatrix(4, 3, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);
+ B = new DoubleMatrix(3, 1, 2.0, 4.0, 8.0);
+ C = new DoubleMatrix(3, 1, -1.0, 2.0, -3.0);
+ D = new DoubleMatrix(3, 3, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
+ E = new DoubleMatrix(3, 3, 1.0, -2.0, 3.0, -4.0, 5.0, -6.0, 7.0, -8.0, 9.0);
+ F = new DoubleMatrix(3, 1, 3.0, 4.0, 7.0);
+ }
+
+ public void testConstructionAndSetGet() {
+ double[][] dataA = {{1.0, 5.0, 9.0}, {2.0, 6.0, 10.0}, {3.0, 7.0, 11.0}, {4.0, 8.0, 12.0}};
+
+ assertEquals(A.rows, 4);
+ assertEquals(A.columns, 3);
+
+ for (int r = 0; r < 4; r++) {
+ for (int c = 0; c < 3; c++) {
+ assertEquals(dataA[r][c], A.get(r, c));
+ }
+ }
+ }
+
+ public void testSetAndGet() {
+ DoubleMatrix M = new DoubleMatrix(3, 3);
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ M.put(i, j, i + j);
+ }
+ }
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ assertEquals((double) i + j, M.get(i, j));
+ }
+ }
+ }
+
+ public void testCopy() {
+ DoubleMatrix M = new DoubleMatrix();
+
+ assertFalse(M.equals(A));
+
+ M.copy(A);
+ assertEquals(M, A);
+ }
+
+ public void testDup() {
+ DoubleMatrix M = A.dup();
+ assertEquals(M, A);
+
+ M.put(0, 0, 2.0);
+ assertFalse(M.equals(A));
+ }
+
+ public void testResize() {
+ DoubleMatrix M = A.dup();
+
+ assertEquals(4, M.rows);
+ assertEquals(3, M.columns);
+
+ M.resize(4, 5);
+ assertEquals(4, M.rows);
+ assertEquals(5, M.columns);
+
+ assertEquals(0.0, M.get(3, 4));
+ }
+
+ public void testReshape() {
+ DoubleMatrix M = new DoubleMatrix(2, 2, 1.0, 2.0, 3.0, 4.0);
+
+ M.reshape(1, 4);
+ assertEquals(1.0, M.get(0, 0));
+ assertEquals(4.0, M.get(0, 3));
+
+ M.reshape(4, 1);
+ assertEquals(1.0, M.get(0, 0));
+ assertEquals(4.0, M.get(3, 0));
+ }
+
+ public void testMmul() {
+ DoubleMatrix R = A.dup();
+ DoubleMatrix result = new DoubleMatrix(4, 1, 94.0, 108.0, 122.0, 136.0);
+
+ A.mmuli(B, R);
+ assertEquals(result, R);
+
+ assertEquals(result, A.mmul(B));
+
+ DoubleMatrix resultDE = new DoubleMatrix(3, 3, 14.0, 16.0, 18.0, -26.0, -31.0, -36.0, 38.0, 46.0, 54.0);
+
+ // In-place with independent operands
+ assertEquals(resultDE, D.mmuli(E, R));
+
+ // In-place on this
+ R = D.dup();
+ assertEquals(resultDE, R.mmuli(E, R));
+
+ // In-place on this
+ R = E.dup();
+ assertEquals(resultDE, D.mmuli(R, R));
+
+ // Fully dynamic
+ assertEquals(resultDE, D.mmul(E));
+ }
+
+ public void testAdd() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, 1.0, 6.0, 5.0);
+
+ DoubleMatrix R = new DoubleMatrix();
+
+ // In-place, but independent operands
+ B.addi(C, R);
+ assertEquals(result, R);
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.addi(C, R));
+
+ // In-place on other
+ R = C.dup();
+ assertEquals(result, B.addi(R, R));
+
+ // fully dynamic
+ assertEquals(result, B.add(C));
+
+ result = new DoubleMatrix(3, 1, 3.0, 5.0, 9.0);
+
+ // In-place, but independent operands
+ assertEquals(result, B.addi(1.0, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.addi(1.0, R));
+
+ // fully dynamic
+ assertEquals(result, B.add(1.0));
+ }
+
+ public void testSub() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, 3.0, 2.0, 11.0);
+
+ DoubleMatrix R = new DoubleMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, B.subi(C, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.subi(C, R));
+
+ // In-place on other
+ R = C.dup();
+ assertEquals(result, B.subi(R, R));
+
+ // fully dynamic
+ assertEquals(result, B.sub(C));
+
+ result = new DoubleMatrix(3, 1, 1.0, 3.0, 7.0);
+
+ // In-place, but independent operands
+ assertEquals(result, B.subi(1.0, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.subi(1.0, R));
+
+ // fully dynamic
+ assertEquals(result, B.sub(1.0));
+ }
+
+ public void testRsub() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, 3.0, 2.0, 11.0);
+
+ DoubleMatrix R = new DoubleMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, C.rsubi(B, R));
+
+ // In-place on this
+ R = C.dup();
+ assertEquals(result, R.rsubi(B, R));
+
+ // In-place on other
+ R = B.dup();
+ assertEquals(result, C.rsubi(R, R));
+
+ // fully dynamic
+ assertEquals(result, C.rsub(B));
+
+ result = new DoubleMatrix(3, 1, -1.0, -3.0, -7.0);
+
+ // In-place, but independent operands
+ assertEquals(result, B.rsubi(1.0, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.rsubi(1.0, R));
+
+ // fully dynamic
+ assertEquals(result, B.rsub(1.0));
+ }
+
+ public void testMul() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, -2.0, 8.0, -24.0);
+
+ DoubleMatrix R = new DoubleMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, B.muli(C, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.muli(C, R));
+
+ // In-place on other
+ R = C.dup();
+ assertEquals(result, B.muli(R, R));
+
+ // fully dynamic
+ assertEquals(result, B.mul(C));
+
+ result = new DoubleMatrix(3, 1, 1.0, 2.0, 4.0);
+
+ // In-place, but independent operands
+ assertEquals(result, B.muli(0.5, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.muli(0.5, R));
+
+ // fully dynamic
+ assertEquals(result, B.mul(0.5));
+ }
+
+ public void testDiv() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, -2.0, 2.0, -2.666666666);
+
+ DoubleMatrix R = new DoubleMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, B.divi(C, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.divi(C, R));
+
+ // In-place on other
+ R = C.dup();
+ assertEquals(result, B.divi(R, R));
+
+ // fully dynamic
+ assertEquals(result, B.div(C));
+
+ result = new DoubleMatrix(3, 1, 1.0, 2.0, 4.0);
+
+ // In-place, but independent operands
+ assertEquals(result, B.divi(2.0, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.divi(2.0, R));
+
+ // fully dynamic
+ assertEquals(result, B.div(2.0));
+ }
+
+ public void testRdiv() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, -2.0, 2.0, -2.666666666);
+
+ DoubleMatrix R = new DoubleMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, C.rdivi(B, R));
+
+ // In-place on this
+ R = C.dup();
+ assertEquals(result, R.rdivi(B, R));
+
+ // In-place on other
+ R = B.dup();
+ assertEquals(result, C.rdivi(R, R));
+
+ // fully dynamic
+ assertEquals(result, C.rdiv(B));
+
+ result = new DoubleMatrix(3, 1, 0.5, 0.25, 0.125);
+
+ // In-place, but independent operands
+ assertEquals(result, B.rdivi(1.0, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.rdivi(1.0, R));
+
+ // fully dynamic
+ assertEquals(result, B.rdiv(1.0));
+ }
+
+ /*# def test_logical(op, result, scalar, result2); <<-EOS
+ public void test#{op.upcase}() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, #{result});
+ DoubleMatrix result2 = new DoubleMatrix(3, 1, #{result2});
+ DoubleMatrix R = new DoubleMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.#{op}i(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.#{op}i(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.#{op}i(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.#{op}(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.#{op}i(#{scalar}, R));
+
+ // fully dynamic
+ assertEquals(result2, B.#{op}(#{scalar}));
+ }
+ EOS
+ end
+ #*/
+ /*# test_logical('lt', '1.0, 0.0, 0.0', 4.0, '1.0, 0.0, 0.0') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public void testLT() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, 1.0, 0.0, 0.0);
+ DoubleMatrix result2 = new DoubleMatrix(3, 1, 1.0, 0.0, 0.0);
+ DoubleMatrix R = new DoubleMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.lti(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.lti(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.lti(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.lt(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.lti(4.0, R));
+
+ // fully dynamic
+ assertEquals(result2, B.lt(4.0));
+ }
+//RJPP-END--------------------------------------------------------------
+ /*# test_logical('le', '1.0, 1.0, 0.0', 4.0, '1.0, 1.0, 0.0') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public void testLE() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, 1.0, 1.0, 0.0);
+ DoubleMatrix result2 = new DoubleMatrix(3, 1, 1.0, 1.0, 0.0);
+ DoubleMatrix R = new DoubleMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.lei(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.lei(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.lei(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.le(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.lei(4.0, R));
+
+ // fully dynamic
+ assertEquals(result2, B.le(4.0));
+ }
+//RJPP-END--------------------------------------------------------------
+ /*# test_logical('gt', '0.0, 0.0, 1.0', 4.0, '0.0, 0.0, 1.0') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public void testGT() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, 0.0, 0.0, 1.0);
+ DoubleMatrix result2 = new DoubleMatrix(3, 1, 0.0, 0.0, 1.0);
+ DoubleMatrix R = new DoubleMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.gti(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.gti(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.gti(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.gt(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.gti(4.0, R));
+
+ // fully dynamic
+ assertEquals(result2, B.gt(4.0));
+ }
+//RJPP-END--------------------------------------------------------------
+ /*# test_logical('ge', '0.0, 1.0, 1.0', 4.0, '0.0, 1.0, 1.0') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public void testGE() {
+ DoubleMatrix result = new DoubleMatrix(3, 1, 0.0, 1.0, 1.0);
+ DoubleMatrix result2 = new DoubleMatrix(3, 1, 0.0, 1.0, 1.0);
+ DoubleMatrix R = new DoubleMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.gei(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.gei(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.gei(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.ge(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.gei(4.0, R));
+
+ // fully dynamic
+ assertEquals(result2, B.ge(4.0));
+ }
+//RJPP-END--------------------------------------------------------------
+ public void testMinMax() {
+ assertEquals(1.0, A.min());
+ assertEquals(12.0, A.max());
+ }
+
+ public void testArgMinMax() {
+ assertEquals(0, A.argmin());
+ assertEquals(11, A.argmax());
+ }
+
+ public void testTranspose() {
+ DoubleMatrix At = A.transpose();
+ assertEquals(1.0, At.get(0, 0));
+ assertEquals(2.0, At.get(0, 1));
+ assertEquals(5.0, At.get(1, 0));
+ }
+
+ public void testGetRowVector() {
+ for (int r = 0; r < A.rows; r++) {
+ A.getRow(r);
+ }
+
+ for (int c = 0; c < A.columns; c++) {
+ A.getColumn(c);
+ }
+
+ A.addiRowVector(new DoubleMatrix(3, 1, 10.0, 100.0, 1000.0));
+ A.addiColumnVector(new DoubleMatrix(1, 4, 10.0, 100.0, 1000.0, 10000.0));
+ }
+
+ public void testPairwiseDistance() {
+ DoubleMatrix D = Geometry.pairwiseSquaredDistances(A, A);
+
+ DoubleMatrix X = new DoubleMatrix(1, 3, 1.0, 0.0, -1.0);
+
+ Geometry.pairwiseSquaredDistances(X, X);
+
+ DoubleMatrix A1 = new DoubleMatrix(1, 2, 1.0, 2.0);
+ DoubleMatrix A2 = new DoubleMatrix(1, 3, 1.0, 2.0, 3.0);
+
+ Geometry.pairwiseSquaredDistances(A1, A2);
+ }
+
+ public void testSwapColumns() {
+ DoubleMatrix AA = A.dup();
+
+ System.out.println("testSwapColumns");
+ AA.swapColumns(1, 2);
+ assertEquals(new DoubleMatrix(4, 3, 1.0, 2.0, 3.0, 4.0, 9.0, 10.0, 11.0, 12.0, 5.0, 6.0, 7.0, 8.0), AA);
+ }
+
+ public void testSwapRows() {
+ DoubleMatrix AA = A.dup();
+
+ AA.swapRows(1, 2);
+ assertEquals(new DoubleMatrix(4, 3, 1.0, 3.0, 2.0, 4.0, 5.0, 7.0, 6.0, 8.0, 9.0, 11.0, 10.0, 12.0), AA);
+ }
+
+ public void testSolve() {
+ DoubleMatrix A = new DoubleMatrix(3, 3, 3.0, 5.0, 6.0, 1.0, 0.0, 0.0, 2.0, 4.0, 0.0);
+ DoubleMatrix B = new DoubleMatrix(3, 1, 1.0, 2.0, 3.0);
+
+ DoubleMatrix Adup = A.dup();
+ DoubleMatrix Bdup = B.dup();
+
+ DoubleMatrix X = Solve.solve(A, B);
+
+ assertEquals(Adup, A);
+ assertEquals(Bdup, B);
+ }
+
+ public void testConstructFromArray() {
+ double[][] data = {
+ {1.0, 2.0, 3.0},
+ {4.0, 5.0, 6.0},
+ {7.0, 8.0, 9.0}
+ };
+
+ DoubleMatrix A = new DoubleMatrix(data);
+
+ for (int r = 0; r < 3; r++) {
+ for (int c = 0; c < 3; c++) {
+ assertEquals(data[r][c], A.get(r, c));
+ }
+ }
+ }
+
+ public void testDiag() {
+ DoubleMatrix A = new DoubleMatrix(new double[][]{
+ {1.0, 2.0, 3.0},
+ {4.0, 5.0, 6.0},
+ {7.0, 8.0, 9.0}
+ });
+
+ assertEquals(new DoubleMatrix(3, 1, 1.0, 5.0, 9.0), A.diag());
+
+ assertEquals(new DoubleMatrix(new double[][]{
+ {1.0, 0.0, 0.0},
+ {0.0, 2.0, 0.0},
+ {0.0, 0.0, 3.0}
+ }), DoubleMatrix.diag(new DoubleMatrix(3, 1, 1.0, 2.0, 3.0)));
+ }
+
+ public void testColumnAndRowMinMax() {
+ assertEquals(new DoubleMatrix(1, 3, 1.0, 5.0, 9.0), A.columnMins());
+ assertEquals(new DoubleMatrix(4, 1, 1.0, 2.0, 3.0, 4.0), A.rowMins());
+ assertEquals(new DoubleMatrix(1, 3, 4.0, 8.0, 12.0), A.columnMaxs());
+ assertEquals(new DoubleMatrix(4, 1, 9.0, 10.0, 11.0, 12.0), A.rowMaxs());
+ int[] i = A.columnArgmins();
+ assertEquals(0, i[0]);
+ assertEquals(0, i[1]);
+ assertEquals(0, i[2]);
+ i = A.columnArgmaxs();
+ assertEquals(3, i[0]);
+ assertEquals(3, i[1]);
+ assertEquals(3, i[2]);
+ i = A.rowArgmins();
+ assertEquals(0, i[0]);
+ assertEquals(0, i[1]);
+ assertEquals(0, i[2]);
+ assertEquals(0, i[3]);
+ i = A.rowArgmaxs();
+ assertEquals(2, i[0]);
+ assertEquals(2, i[1]);
+ assertEquals(2, i[2]);
+ assertEquals(2, i[3]);
+ }
+
+ public void testToArray() {
+ assertTrue(Arrays.equals(new double[]{2.0, 4.0, 8.0}, B.toArray()));
+ assertTrue(Arrays.equals(new int[]{2, 4, 8}, B.toIntArray()));
+ assertTrue(Arrays.equals(new boolean[]{true, true, true}, B.toBooleanArray()));
+ }
+
+ public void testLoadAsciiFile() {
+ try {
+ DoubleMatrix result = DoubleMatrix.loadAsciiFile("/home/mikio/datasets/banana/banana_train_data_1.asc");
+ result.print();
+ } catch (Exception e) {
+ fail("Caught exception " + e);
+ }
+ }
+
+ public void testRanges() {
+ A.print();
+ A.get(interval(0, 2), interval(0, 1)).print();
+ }
+}
diff --git a/test/org/jblas/la/TestFloatMatrix.java b/test/org/jblas/la/TestFloatMatrix.java
new file mode 100644
index 0000000..9b3b737
--- /dev/null
+++ b/test/org/jblas/la/TestFloatMatrix.java
@@ -0,0 +1,641 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.FloatMatrix;
+import org.jblas.la.Geometry;
+import org.jblas.la.Solve;
+import junit.framework.TestCase;
+import java.util.Arrays;
+import static org.jblas.la.ranges.RangeUtils.*;
+
+public class TestFloatMatrix extends TestCase {
+
+ FloatMatrix A, B, C, D, E, F;
+
+ public void setUp() {
+ A = new FloatMatrix(4, 3, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f);
+ B = new FloatMatrix(3, 1, 2.0f, 4.0f, 8.0f);
+ C = new FloatMatrix(3, 1, -1.0f, 2.0f, -3.0f);
+ D = new FloatMatrix(3, 3, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f);
+ E = new FloatMatrix(3, 3, 1.0f, -2.0f, 3.0f, -4.0f, 5.0f, -6.0f, 7.0f, -8.0f, 9.0f);
+ F = new FloatMatrix(3, 1, 3.0f, 4.0f, 7.0f);
+ }
+
+ public void testConstructionAndSetGet() {
+ float[][] dataA = {{1.0f, 5.0f, 9.0f}, {2.0f, 6.0f, 10.0f}, {3.0f, 7.0f, 11.0f}, {4.0f, 8.0f, 12.0f}};
+
+ assertEquals(A.rows, 4);
+ assertEquals(A.columns, 3);
+
+ for (int r = 0; r < 4; r++) {
+ for (int c = 0; c < 3; c++) {
+ assertEquals(dataA[r][c], A.get(r, c));
+ }
+ }
+ }
+
+ public void testSetAndGet() {
+ FloatMatrix M = new FloatMatrix(3, 3);
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ M.put(i, j, i + j);
+ }
+ }
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ assertEquals((float) i + j, M.get(i, j));
+ }
+ }
+ }
+
+ public void testCopy() {
+ FloatMatrix M = new FloatMatrix();
+
+ assertFalse(M.equals(A));
+
+ M.copy(A);
+ assertEquals(M, A);
+ }
+
+ public void testDup() {
+ FloatMatrix M = A.dup();
+ assertEquals(M, A);
+
+ M.put(0, 0, 2.0f);
+ assertFalse(M.equals(A));
+ }
+
+ public void testResize() {
+ FloatMatrix M = A.dup();
+
+ assertEquals(4, M.rows);
+ assertEquals(3, M.columns);
+
+ M.resize(4, 5);
+ assertEquals(4, M.rows);
+ assertEquals(5, M.columns);
+
+ assertEquals(0.0f, M.get(3, 4));
+ }
+
+ public void testReshape() {
+ FloatMatrix M = new FloatMatrix(2, 2, 1.0f, 2.0f, 3.0f, 4.0f);
+
+ M.reshape(1, 4);
+ assertEquals(1.0f, M.get(0, 0));
+ assertEquals(4.0f, M.get(0, 3));
+
+ M.reshape(4, 1);
+ assertEquals(1.0f, M.get(0, 0));
+ assertEquals(4.0f, M.get(3, 0));
+ }
+
+ public void testMmul() {
+ FloatMatrix R = A.dup();
+ FloatMatrix result = new FloatMatrix(4, 1, 94.0f, 108.0f, 122.0f, 136.0f);
+
+ A.mmuli(B, R);
+ assertEquals(result, R);
+
+ assertEquals(result, A.mmul(B));
+
+ FloatMatrix resultDE = new FloatMatrix(3, 3, 14.0f, 16.0f, 18.0f, -26.0f, -31.0f, -36.0f, 38.0f, 46.0f, 54.0f);
+
+ // In-place with independent operands
+ assertEquals(resultDE, D.mmuli(E, R));
+
+ // In-place on this
+ R = D.dup();
+ assertEquals(resultDE, R.mmuli(E, R));
+
+ // In-place on this
+ R = E.dup();
+ assertEquals(resultDE, D.mmuli(R, R));
+
+ // Fully dynamic
+ assertEquals(resultDE, D.mmul(E));
+ }
+
+ public void testAdd() {
+ FloatMatrix result = new FloatMatrix(3, 1, 1.0f, 6.0f, 5.0f);
+
+ FloatMatrix R = new FloatMatrix();
+
+ // In-place, but independent operands
+ B.addi(C, R);
+ assertEquals(result, R);
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.addi(C, R));
+
+ // In-place on other
+ R = C.dup();
+ assertEquals(result, B.addi(R, R));
+
+ // fully dynamic
+ assertEquals(result, B.add(C));
+
+ result = new FloatMatrix(3, 1, 3.0f, 5.0f, 9.0f);
+
+ // In-place, but independent operands
+ assertEquals(result, B.addi(1.0f, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.addi(1.0f, R));
+
+ // fully dynamic
+ assertEquals(result, B.add(1.0f));
+ }
+
+ public void testSub() {
+ FloatMatrix result = new FloatMatrix(3, 1, 3.0f, 2.0f, 11.0f);
+
+ FloatMatrix R = new FloatMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, B.subi(C, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.subi(C, R));
+
+ // In-place on other
+ R = C.dup();
+ assertEquals(result, B.subi(R, R));
+
+ // fully dynamic
+ assertEquals(result, B.sub(C));
+
+ result = new FloatMatrix(3, 1, 1.0f, 3.0f, 7.0f);
+
+ // In-place, but independent operands
+ assertEquals(result, B.subi(1.0f, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.subi(1.0f, R));
+
+ // fully dynamic
+ assertEquals(result, B.sub(1.0f));
+ }
+
+ public void testRsub() {
+ FloatMatrix result = new FloatMatrix(3, 1, 3.0f, 2.0f, 11.0f);
+
+ FloatMatrix R = new FloatMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, C.rsubi(B, R));
+
+ // In-place on this
+ R = C.dup();
+ assertEquals(result, R.rsubi(B, R));
+
+ // In-place on other
+ R = B.dup();
+ assertEquals(result, C.rsubi(R, R));
+
+ // fully dynamic
+ assertEquals(result, C.rsub(B));
+
+ result = new FloatMatrix(3, 1, -1.0f, -3.0f, -7.0f);
+
+ // In-place, but independent operands
+ assertEquals(result, B.rsubi(1.0f, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.rsubi(1.0f, R));
+
+ // fully dynamic
+ assertEquals(result, B.rsub(1.0f));
+ }
+
+ public void testMul() {
+ FloatMatrix result = new FloatMatrix(3, 1, -2.0f, 8.0f, -24.0f);
+
+ FloatMatrix R = new FloatMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, B.muli(C, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.muli(C, R));
+
+ // In-place on other
+ R = C.dup();
+ assertEquals(result, B.muli(R, R));
+
+ // fully dynamic
+ assertEquals(result, B.mul(C));
+
+ result = new FloatMatrix(3, 1, 1.0f, 2.0f, 4.0f);
+
+ // In-place, but independent operands
+ assertEquals(result, B.muli(0.5f, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.muli(0.5f, R));
+
+ // fully dynamic
+ assertEquals(result, B.mul(0.5f));
+ }
+
+ public void testDiv() {
+ FloatMatrix result = new FloatMatrix(3, 1, -2.0f, 2.0f, -2.666666666f);
+
+ FloatMatrix R = new FloatMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, B.divi(C, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.divi(C, R));
+
+ // In-place on other
+ R = C.dup();
+ assertEquals(result, B.divi(R, R));
+
+ // fully dynamic
+ assertEquals(result, B.div(C));
+
+ result = new FloatMatrix(3, 1, 1.0f, 2.0f, 4.0f);
+
+ // In-place, but independent operands
+ assertEquals(result, B.divi(2.0f, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.divi(2.0f, R));
+
+ // fully dynamic
+ assertEquals(result, B.div(2.0f));
+ }
+
+ public void testRdiv() {
+ FloatMatrix result = new FloatMatrix(3, 1, -2.0f, 2.0f, -2.666666666f);
+
+ FloatMatrix R = new FloatMatrix();
+
+ // In-place, but independent operands
+ assertEquals(result, C.rdivi(B, R));
+
+ // In-place on this
+ R = C.dup();
+ assertEquals(result, R.rdivi(B, R));
+
+ // In-place on other
+ R = B.dup();
+ assertEquals(result, C.rdivi(R, R));
+
+ // fully dynamic
+ assertEquals(result, C.rdiv(B));
+
+ result = new FloatMatrix(3, 1, 0.5f, 0.25f, 0.125f);
+
+ // In-place, but independent operands
+ assertEquals(result, B.rdivi(1.0f, R));
+
+ // In-place on this
+ R = B.dup();
+ assertEquals(result, R.rdivi(1.0f, R));
+
+ // fully dynamic
+ assertEquals(result, B.rdiv(1.0f));
+ }
+
+ /*# def test_logical(op, result, scalar, result2); <<-EOS
+ public void test#{op.upcase}() {
+ FloatMatrix result = new FloatMatrix(3, 1, #{result});
+ FloatMatrix result2 = new FloatMatrix(3, 1, #{result2});
+ FloatMatrix R = new FloatMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.#{op}i(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.#{op}i(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.#{op}i(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.#{op}(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.#{op}i(#{scalar}, R));
+
+ // fully dynamic
+ assertEquals(result2, B.#{op}(#{scalar}));
+ }
+ EOS
+ end
+ #*/
+ /*# test_logical('lt', '1.0f, 0.0f, 0.0f', 4.0f, '1.0f, 0.0f, 0.0f') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public void testLT() {
+ FloatMatrix result = new FloatMatrix(3, 1, 1.0f, 0.0f, 0.0f);
+ FloatMatrix result2 = new FloatMatrix(3, 1, 1.0f, 0.0f, 0.0f);
+ FloatMatrix R = new FloatMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.lti(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.lti(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.lti(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.lt(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.lti(4.0f, R));
+
+ // fully dynamic
+ assertEquals(result2, B.lt(4.0f));
+ }
+//RJPP-END--------------------------------------------------------------
+ /*# test_logical('le', '1.0f, 1.0f, 0.0f', 4.0f, '1.0f, 1.0f, 0.0f') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public void testLE() {
+ FloatMatrix result = new FloatMatrix(3, 1, 1.0f, 1.0f, 0.0f);
+ FloatMatrix result2 = new FloatMatrix(3, 1, 1.0f, 1.0f, 0.0f);
+ FloatMatrix R = new FloatMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.lei(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.lei(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.lei(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.le(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.lei(4.0f, R));
+
+ // fully dynamic
+ assertEquals(result2, B.le(4.0f));
+ }
+//RJPP-END--------------------------------------------------------------
+ /*# test_logical('gt', '0.0f, 0.0f, 1.0f', 4.0f, '0.0f, 0.0f, 1.0f') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public void testGT() {
+ FloatMatrix result = new FloatMatrix(3, 1, 0.0f, 0.0f, 1.0f);
+ FloatMatrix result2 = new FloatMatrix(3, 1, 0.0f, 0.0f, 1.0f);
+ FloatMatrix R = new FloatMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.gti(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.gti(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.gti(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.gt(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.gti(4.0f, R));
+
+ // fully dynamic
+ assertEquals(result2, B.gt(4.0f));
+ }
+//RJPP-END--------------------------------------------------------------
+ /*# test_logical('ge', '0.0f, 1.0f, 1.0f', 4.0f, '0.0f, 1.0f, 1.0f') #*/
+//RJPP-BEGIN------------------------------------------------------------
+ public void testGE() {
+ FloatMatrix result = new FloatMatrix(3, 1, 0.0f, 1.0f, 1.0f);
+ FloatMatrix result2 = new FloatMatrix(3, 1, 0.0f, 1.0f, 1.0f);
+ FloatMatrix R = new FloatMatrix();
+
+ // in-place but independent operands
+ assertEquals(result, B.gei(F, R));
+
+ // in-place but in other
+ R = F.dup();
+ assertEquals(result, B.gei(R, R));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result, R.gei(F, R));
+
+ // fully dynamic
+ assertEquals(result, B.ge(F));
+
+ // in-place in this
+ R = B.dup();
+ assertEquals(result2, R.gei(4.0f, R));
+
+ // fully dynamic
+ assertEquals(result2, B.ge(4.0f));
+ }
+//RJPP-END--------------------------------------------------------------
+ public void testMinMax() {
+ assertEquals(1.0f, A.min());
+ assertEquals(12.0f, A.max());
+ }
+
+ public void testArgMinMax() {
+ assertEquals(0, A.argmin());
+ assertEquals(11, A.argmax());
+ }
+
+ public void testTranspose() {
+ FloatMatrix At = A.transpose();
+ assertEquals(1.0f, At.get(0, 0));
+ assertEquals(2.0f, At.get(0, 1));
+ assertEquals(5.0f, At.get(1, 0));
+ }
+
+ public void testGetRowVector() {
+ for (int r = 0; r < A.rows; r++) {
+ A.getRow(r);
+ }
+
+ for (int c = 0; c < A.columns; c++) {
+ A.getColumn(c);
+ }
+
+ A.addiRowVector(new FloatMatrix(3, 1, 10.0f, 100.0f, 1000.0f));
+ A.addiColumnVector(new FloatMatrix(1, 4, 10.0f, 100.0f, 1000.0f, 10000.0f));
+ }
+
+ public void testPairwiseDistance() {
+ FloatMatrix D = Geometry.pairwiseSquaredDistances(A, A);
+
+ FloatMatrix X = new FloatMatrix(1, 3, 1.0f, 0.0f, -1.0f);
+
+ Geometry.pairwiseSquaredDistances(X, X);
+
+ FloatMatrix A1 = new FloatMatrix(1, 2, 1.0f, 2.0f);
+ FloatMatrix A2 = new FloatMatrix(1, 3, 1.0f, 2.0f, 3.0f);
+
+ Geometry.pairwiseSquaredDistances(A1, A2);
+ }
+
+ public void testSwapColumns() {
+ FloatMatrix AA = A.dup();
+
+ System.out.println("testSwapColumns");
+ AA.swapColumns(1, 2);
+ assertEquals(new FloatMatrix(4, 3, 1.0f, 2.0f, 3.0f, 4.0f, 9.0f, 10.0f, 11.0f, 12.0f, 5.0f, 6.0f, 7.0f, 8.0f), AA);
+ }
+
+ public void testSwapRows() {
+ FloatMatrix AA = A.dup();
+
+ AA.swapRows(1, 2);
+ assertEquals(new FloatMatrix(4, 3, 1.0f, 3.0f, 2.0f, 4.0f, 5.0f, 7.0f, 6.0f, 8.0f, 9.0f, 11.0f, 10.0f, 12.0f), AA);
+ }
+
+ public void testSolve() {
+ FloatMatrix A = new FloatMatrix(3, 3, 3.0f, 5.0f, 6.0f, 1.0f, 0.0f, 0.0f, 2.0f, 4.0f, 0.0f);
+ FloatMatrix B = new FloatMatrix(3, 1, 1.0f, 2.0f, 3.0f);
+
+ FloatMatrix Adup = A.dup();
+ FloatMatrix Bdup = B.dup();
+
+ FloatMatrix X = Solve.solve(A, B);
+
+ assertEquals(Adup, A);
+ assertEquals(Bdup, B);
+ }
+
+ public void testConstructFromArray() {
+ float[][] data = {
+ {1.0f, 2.0f, 3.0f},
+ {4.0f, 5.0f, 6.0f},
+ {7.0f, 8.0f, 9.0f}
+ };
+
+ FloatMatrix A = new FloatMatrix(data);
+
+ for (int r = 0; r < 3; r++) {
+ for (int c = 0; c < 3; c++) {
+ assertEquals(data[r][c], A.get(r, c));
+ }
+ }
+ }
+
+ public void testDiag() {
+ FloatMatrix A = new FloatMatrix(new float[][]{
+ {1.0f, 2.0f, 3.0f},
+ {4.0f, 5.0f, 6.0f},
+ {7.0f, 8.0f, 9.0f}
+ });
+
+ assertEquals(new FloatMatrix(3, 1, 1.0f, 5.0f, 9.0f), A.diag());
+
+ assertEquals(new FloatMatrix(new float[][]{
+ {1.0f, 0.0f, 0.0f},
+ {0.0f, 2.0f, 0.0f},
+ {0.0f, 0.0f, 3.0f}
+ }), FloatMatrix.diag(new FloatMatrix(3, 1, 1.0f, 2.0f, 3.0f)));
+ }
+
+ public void testColumnAndRowMinMax() {
+ assertEquals(new FloatMatrix(1, 3, 1.0f, 5.0f, 9.0f), A.columnMins());
+ assertEquals(new FloatMatrix(4, 1, 1.0f, 2.0f, 3.0f, 4.0f), A.rowMins());
+ assertEquals(new FloatMatrix(1, 3, 4.0f, 8.0f, 12.0f), A.columnMaxs());
+ assertEquals(new FloatMatrix(4, 1, 9.0f, 10.0f, 11.0f, 12.0f), A.rowMaxs());
+ int[] i = A.columnArgmins();
+ assertEquals(0, i[0]);
+ assertEquals(0, i[1]);
+ assertEquals(0, i[2]);
+ i = A.columnArgmaxs();
+ assertEquals(3, i[0]);
+ assertEquals(3, i[1]);
+ assertEquals(3, i[2]);
+ i = A.rowArgmins();
+ assertEquals(0, i[0]);
+ assertEquals(0, i[1]);
+ assertEquals(0, i[2]);
+ assertEquals(0, i[3]);
+ i = A.rowArgmaxs();
+ assertEquals(2, i[0]);
+ assertEquals(2, i[1]);
+ assertEquals(2, i[2]);
+ assertEquals(2, i[3]);
+ }
+
+ public void testToArray() {
+ assertTrue(Arrays.equals(new float[]{2.0f, 4.0f, 8.0f}, B.toArray()));
+ assertTrue(Arrays.equals(new int[]{2, 4, 8}, B.toIntArray()));
+ assertTrue(Arrays.equals(new boolean[]{true, true, true}, B.toBooleanArray()));
+ }
+
+ public void testLoadAsciiFile() {
+ try {
+ FloatMatrix result = FloatMatrix.loadAsciiFile("/home/mikio/datasets/banana/banana_train_data_1.asc");
+ result.print();
+ } catch (Exception e) {
+ fail("Caught exception " + e);
+ }
+ }
+
+ public void testRanges() {
+ A.print();
+ A.get(interval(0, 2), interval(0, 1)).print();
+ }
+}
diff --git a/test/org/jblas/la/TestGeometry.java b/test/org/jblas/la/TestGeometry.java
new file mode 100644
index 0000000..70efc93
--- /dev/null
+++ b/test/org/jblas/la/TestGeometry.java
@@ -0,0 +1,78 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.DoubleMatrix;
+import org.jblas.la.Geometry;
+import junit.framework.TestCase;
+
+public class TestGeometry extends TestCase {
+ public void testCenter() {
+ DoubleMatrix x = new DoubleMatrix(3, 1, 1.0, 2.0, 3.0);
+
+ Geometry.center(x);
+
+ assertEquals(new DoubleMatrix(3, 1, -1.0, 0.0, 1.0), x);
+
+ DoubleMatrix M = new DoubleMatrix(new double[][] {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0}});
+
+ //M.print();
+
+ DoubleMatrix MR = Geometry.centerRows(M.dup());
+ DoubleMatrix MC = Geometry.centerColumns(M.dup());
+
+ //MR.print();
+ //MC.print();
+
+ assertEquals(new DoubleMatrix(new double[][] {{-1.0, 0.0, 1.0}, {-1.0, 0.0, 1.0}, {-1.0, 0.0, 1.0}}), MR);
+ assertEquals(new DoubleMatrix(new double[][] {{-3.0, -3.0, -3.0}, {0.0, 0.0, 0.0}, {3.0, 3.0, 3.0}}), MC);
+ }
+
+ public void testPwDist() {
+ DoubleMatrix M = new DoubleMatrix(3, 5, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);
+
+ DoubleMatrix D = Geometry.pairwiseSquaredDistances(M, M);
+
+ D.print();
+
+ M = M.transpose();
+
+ D = Geometry.pairwiseSquaredDistances(M, M);
+
+ D.print();
+ }
+}
diff --git a/test/org/jblas/la/TestMatrixFunctions.java b/test/org/jblas/la/TestMatrixFunctions.java
new file mode 100644
index 0000000..1ab992a
--- /dev/null
+++ b/test/org/jblas/la/TestMatrixFunctions.java
@@ -0,0 +1,49 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import org.jblas.la.DoubleMatrix;
+import junit.framework.TestCase;
+import static org.jblas.la.MatrixFunctions.*;
+
+public class TestMatrixFunctions extends TestCase {
+ public void testAbs() {
+ DoubleMatrix m = new DoubleMatrix(1, 2, 1.0, -1.0);
+
+ assertEquals(new DoubleMatrix(1, 2, 1.0, 1.0), abs(m));
+ }
+}
diff --git a/test/org/jblas/la/TestSolve.java b/test/org/jblas/la/TestSolve.java
new file mode 100644
index 0000000..8c535e8
--- /dev/null
+++ b/test/org/jblas/la/TestSolve.java
@@ -0,0 +1,50 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+import junit.framework.TestCase;
+
+import org.jblas.la.*;
+
+public class TestSolve extends TestCase {
+ public void testFaultySolveSymmetric() {
+ DoubleMatrix A = new DoubleMatrix(3, 3, 2d, 1d, 0d, 2d, 1d, 2d, 0d, 1d, 2d);
+ DoubleMatrix x = new DoubleMatrix(1, 3, 1d, 2d, 3d);
+
+ Solve.solveSymmetric(A, x);
+ }
+}
diff --git a/test/org/jblas/la/TicToc.java b/test/org/jblas/la/TicToc.java
new file mode 100644
index 0000000..4de4789
--- /dev/null
+++ b/test/org/jblas/la/TicToc.java
@@ -0,0 +1,70 @@
+// --- BEGIN LICENSE BLOCK ---
+/*
+ * Copyright (c) 2009, Mikio L. Braun
+ * 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 Technische Universität Berlin 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
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// --- END LICENSE BLOCK ---
+
+package org.jblas.la;
+
+public class TicToc {
+ private static long savedTime;
+
+ public static void tic(String message) {
+ System.out.print(message);
+ System.out.print("...");
+ System.out.flush();
+ savedTime = System.currentTimeMillis();
+ }
+
+ public static void tic(String message, Object... args) {
+ System.out.printf(message, args);
+ System.out.print("...");
+ System.out.flush();
+ savedTime = System.currentTimeMillis();
+ }
+
+ public static double toc() {
+ long elapsedTime = System.currentTimeMillis() - savedTime;
+ System.out.printf(" (%.2fs)", (double)elapsedTime / 1000d);
+ System.out.println();
+ return (double)elapsedTime / 1000d;
+ }
+
+ public static void main(String args[]) {
+ tic("counting to 10000000");
+ int counter = 0;
+ for (int i = 0; i < 10000000; i++)
+ counter++;
+ toc();
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jblas.git
More information about the pkg-java-commits
mailing list