[jblas] 04/24: Imported Upstream version 0.3

Tony Mancill tmancill at moszumanska.debian.org
Sun Jan 5 05:45:57 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 1ecea6e9b671bdfc5c3cb419fed7204fda7f731f
Author: tony mancill <tmancill at debian.org>
Date:   Tue Dec 31 15:19:19 2013 -0800

    Imported Upstream version 0.3
---
 .classpath                                         |    9 +
 .project                                           |   23 +
 INSTALL                                            |   55 +-
 Makefile                                           |  253 +-
 README                                             |   10 +-
 RELEASE_NOTES                                      |   73 +
 build.xml                                          |  182 +-
 config/config.rb                                   |   12 +
 config/configure.rb                                |  112 +-
 config/path.rb                                     |   15 +
 configure                                          |    8 +-
 docs/jblas-logo.png                                |  Bin 0 -> 5109 bytes
 docs/jblas-logo.svg                                |  113 +
 docs/jblas-thumb.png                               |  Bin 0 -> 960 bytes
 docs/render.rb                                     |   10 +
 docs/tutorial.textile                              |  111 +
 examples/complex.rb                                |   47 +
 examples/jmatrix.rb                                |  183 ++
 examples/test_abitofml.rb                          |  118 +
 examples/test_matrix.rb                            |   96 +
 examples/test_time_eigen.rb                        |   35 +
 examples/tictoc.rb                                 |   33 +
 fortranwrapper.dump                                |  Bin 42859 -> 49328 bytes
 nbproject/project.xml                              |   20 +-
 scripts/class_to_float.rb                          |   10 +-
 scripts/fortran/c.rb                               |  175 --
 scripts/fortran/java.rb                            |  102 +-
 scripts/{fortran.rb => fortran/parser.rb}          |  280 +-
 scripts/fortran/types.rb                           |  192 ++
 scripts/fortranwrapper.rb                          |   10 +-
 scripts/java-class.java                            |   45 +-
 scripts/java-impl.c                                |    2 +-
 scripts/render-textile.rb                          |   34 +
 scripts/static_class_to_float.rb                   |   10 +-
 config/path.rb => scripts/template_context.rb      |   42 +-
 scripts/test_fortranwrapper                        |    0
 src/org/jblas/{core => }/ComplexDouble.java        |    2 +-
 src/org/jblas/{la => }/ComplexDoubleMatrix.java    | 3093 ++++++++++----------
 src/org/jblas/{core => }/ComplexFloat.java         |    2 +-
 src/org/jblas/{la => }/ComplexFloatMatrix.java     | 3093 ++++++++++----------
 src/org/jblas/ConvertsToDoubleMatrix.java          |   14 +
 src/org/jblas/ConvertsToFloatMatrix.java           |   14 +
 src/org/jblas/Decompose.java                       |   82 +
 src/org/jblas/{la => }/DoubleFunction.java         |    2 +-
 src/org/jblas/{la => }/DoubleMatrix.java           |  304 +-
 src/org/jblas/{la => }/Eigen.java                  |    2 +-
 src/org/jblas/{la => }/FloatFunction.java          |    2 +-
 src/org/jblas/{la => }/FloatMatrix.java            |  304 +-
 src/org/jblas/{la => }/Geometry.java               |    2 +-
 src/org/jblas/{la => }/JavaBlas.java               |    4 +-
 src/org/jblas/{la => }/MatrixFunctions.java        |   23 +-
 src/org/jblas/{la/Blas.java => NativeBlas.java}    |  101 +-
 src/org/jblas/{la => }/SimpleBlas.java             |  215 +-
 src/org/jblas/{la => }/Solve.java                  |    2 +-
 src/org/jblas/{la => }/Trigonometry.java           |   62 +-
 .../exceptions/LapackArgumentException.java        |   36 +-
 .../exceptions/LapackConvergenceException.java     |    2 +-
 .../jblas/{la => }/exceptions/LapackException.java |   34 +-
 .../exceptions/LapackPositivityException.java      |   15 +
 .../LapackSingularityException.java}               |   11 +-
 .../jblas/{la => }/exceptions/SizeException.java   |    2 +-
 .../jblas/{core => exceptions}/package-info.java   |    7 +-
 src/org/jblas/la/exceptions/package-info.java      |    5 -
 src/org/jblas/la/ranges/package-info.java          |    5 -
 src/org/jblas/{la => }/package-info.java           |    2 +-
 src/org/jblas/{la => }/ranges/AllRange.java        |    4 +-
 src/org/jblas/{la => }/ranges/IndicesRange.java    |    4 +-
 src/org/jblas/{la => }/ranges/IntervalRange.java   |    2 +-
 src/org/jblas/{la => }/ranges/PointRange.java      |    2 +-
 src/org/jblas/{la => }/ranges/Range.java           |    2 +-
 src/org/jblas/{la => }/ranges/RangeUtils.java      |    6 +-
 src/org/jblas/{la => ranges}/package-info.java     |    7 +-
 src/org/jblas/{core => util}/Functions.java        |    5 +-
 src/org/jblas/util/LibraryLoader.java              |  148 +-
 src/org/jblas/util/Permutations.java               |   86 +
 src/org/jblas/util/SanityChecks.java               |   83 +
 src/overview.html                                  |   10 +-
 src/overview.textile                               |    2 +-
 test/org/jblas/{la => }/BenchmarkAccess.java       |    8 +-
 test/org/jblas/{la => }/BenchmarkComplex.java      |    5 +-
 test/org/jblas/{la => }/BenchmarkElementwise.java  |    6 +-
 test/org/jblas/{la => }/BenchmarkMatrix.java       |    7 +-
 .../jblas/{la => }/ComplexDoubleMatrixTest.java    |    5 +-
 test/org/jblas/{la => }/DemoImages.java            |   16 +-
 test/org/jblas/{core => }/Dynamic.java             |   26 +-
 test/org/jblas/{la => }/SimpleBlasTest.java        |    4 +-
 test/org/jblas/{la => }/TestBlasDouble.java        |   26 +-
 test/org/jblas/{la => }/TestBlasDoubleComplex.java |   10 +-
 test/org/jblas/{la => }/TestBlasFloat.java         |   26 +-
 test/org/jblas/{core => }/TestComplexFloat.java    |    3 +-
 test/org/jblas/{la => }/TestDoubleMatrix.java      |   40 +-
 .../jblas/{la/EigenTest.java => TestEigen.java}    |   24 +-
 test/org/jblas/{la => }/TestFloatMatrix.java       |   40 +-
 test/org/jblas/{la => }/TestGeometry.java          |    4 +-
 test/org/jblas/{la => }/TestMatrixFunctions.java   |    5 +-
 test/org/jblas/{la => }/TestSolve.java             |    4 +-
 test/org/jblas/{la => }/TicToc.java                |    2 +-
 97 files changed, 6245 insertions(+), 4239 deletions(-)

diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..5b86d24
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3.8.1"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/.project b/.project
new file mode 100644
index 0000000..fb01a39
--- /dev/null
+++ b/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Java-Blas</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.rubypeople.rdt.core.rubybuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.rubypeople.rdt.core.rubynature</nature>
+	</natures>
+</projectDescription>
diff --git a/INSTALL b/INSTALL
index 06048d3..0b957e6 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,4 +1,7 @@
-INSTALL Guide v0.1 - March 30, 2009
+INSTALL Guide 
+
+Version 0.2, May 8, 2009
+Version 0.1, March 28, 2009
 
 jblas depends on a BLAS and LAPACK library for most of its
 computational intensive parts. I recommend getting a high-quality
@@ -28,16 +31,16 @@ Prerequisites:
 
 1. Run "./configure".
 
-2. Running "ant clean all" should do the job ;)
+2. Running "ant clean jar" should do the job ;)
 
 
 INSTALLING JBLAS
 
-1. Add "jblas.jar" to your CLASSPATH
+1. Add "jblas-0.2.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
+   don't want to do this, extract the dynamic library from jblas-0.2.jar
    and copy it somewhere where it can be found.
 
    For Linux, use LD_LIBRARY_PATH, for Windows, PATH
@@ -68,6 +71,50 @@ The configure script understands the following options:
    print this help
 
 
+JAR BUILDING OPTIONS
+
+You can generate different kinds of jar-files. By default, you get a
+jar file which contains the JNI wrapper code for your platform which
+is named jblas-VERSION.jar
+
+"make all-jars" generates a number of other options, including
+
+jblas-VERSION-OS_NAME-OS_ARCH.jar 
+    - default build for your platform, links BLAS / LAPACK / ATLAS
+      libraries dynamically if available
+
+jblas-VERSION-OS_NAME-OS_ARCH-static.jar 
+    - with static libraries, for standalone deployment
+
+jblas-VERSION-multiplatform.jar
+    - with libraries for all available platforms, for OS independent
+      standalone deployment.
+      
+The available platforms are those which are found in the native-libs
+directory. In order to build these, merge the contents of the
+native-libs directory from different platforms.
+
+In other words, for each OS, you do
+
+  > ./configure --static-libs ... further options ...
+  > ant compile-native
+
+And then collect the files in native-libs. For example, your
+native-libs directory can then look like this:
+
+  > find native-libs
+  native-libs/
+  native-libs/Linux
+  native-libs/Linux/i386
+  native-libs/Linux/i386/libjblas.so
+  native-libs/Windows
+  native-libs/Windows/x86
+  native-libs/Windows/x86/jblas.dll
+
+If you now run "make all-jars", you get a jar file which can be used
+on the Linux and Windows platform.
+
+
 FURTHER BUILD OPTIONS
 =====================
 
diff --git a/Makefile b/Makefile
index b0ceaf8..4779311 100644
--- a/Makefile
+++ b/Makefile
@@ -1,113 +1,140 @@
-## --- 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 ..
+## --- 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
+
+# generate path from package name
+PACKAGE_PATH=$(subst .,/,$(PACKAGE))
+
+LIB_PATH=native-libs/$(LINKAGE)/$(OS_NAME)/$(OS_ARCH)
+
+#
+# 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 : $(LIB_PATH)/$(LIB)jblas.$(SO)
+
+generate-wrapper: src/$(PACKAGE_PATH)/NativeBlas.java native/NativeBlas.c
+
+clean:
+	rm -f native/*.o native/*.$(SO) $(LIB_PATH)/*.$(SO) src/$(PACKAGE_PATH)/NativeBlas.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)/NativeBlas.java native/NativeBlas.c: scripts/fortranwrapper.rb scripts/fortran/types.rb scripts/fortran/java.rb scripts/java-class.java scripts/java-impl.c
+	$(RUBY) scripts/fortranwrapper.rb $(PACKAGE) NativeBlas \
+	$(BLAS)/*.f \
+	$(LAPACK)/[sd]gesv.f \
+	$(LAPACK)/[sd]sysv.f \
+	$(LAPACK)/[sd]syev.f \
+	$(LAPACK)/[sd]syev[rdx].f \
+	$(LAPACK)/[sd]posv.f \
+	$(LAPACK)/[sdcz]geev.f \
+	$(LAPACK)/[sd]getrf.f \
+    $(LAPACK)/[sd]potrf.f 
+
+$(LIB_PATH)/$(LIB)jblas.$(SO) : native/NativeBlas.$(SO)
+	mkdir -p $(LIB_PATH)
+	mv $< $@
+
+#
+# For testing
+#
+VERSION=0.3
+
+make test-dist:
+	ant clean tar
+	rm -rf jblas-$(VERSION)
+	tar xzvf jblas-$(VERSION).tgz
+	cd jblas-$(VERSION)
+	./configure
+	ant clean jar
+	java -cp jblas-$(VERSION).jar org.jblas.util.SanityChecks
+	cd ..
+
+#
+# Building different kinds of jar files
+#
+all-jars:
+	ant clean-jars
+	./configure --keep-options $$(cat configure.options)
+	ant jar 
+	ant lean-jar
+	./configure --keep-options --static-libs $$(cat configure.options)
+	ant compile-native static-jar fat-jar
+
+all-static-jars:
+	./configure --keep-options --static-libs $$(cat configure.options)
+	ant compile-native
+	for os_name in native-libs/*; do \
+	  for os_arch in $$os_name/* ; do \
+	    ant static-jar -Dos_name=$$(basename $$os_name) \
+		-Dos_arch=$$(basename $$os_arch); \
+	  done; \
+	done
diff --git a/README b/README
index 5f63eb4..8243033 100644
--- a/README
+++ b/README
@@ -1,12 +1,16 @@
 jblas is a matrix library for Java which uses existing high
 performance BLAS and LAPACK libraries like ATLAS.
 
+Version 0.3, September 17, 2009
+Version 0.2, May 8, 2009
 Version 0.1, March 28, 2009
 
+see also the file RELEASE_NOTES
+
 INSTALL
 
-In principle, all you need is the jblas.jar in your
-classpath. jblas.jar will then automagically extract your platform
+In principle, all you need is the jblas-0.2.jar in your
+classpath. jblas-0.2.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).
@@ -31,7 +35,7 @@ details.
 
 HOW TO GET STARTED
 
-Have a look at javadoc/index.html and javadoc/org/jblas/la/DoubleMatrix.html
+Have a look at javadoc/index.html and javadoc/org/jblas/DoubleMatrix.html
 
 
 LICENSE
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
new file mode 100644
index 0000000..da2f0c7
--- /dev/null
+++ b/RELEASE_NOTES
@@ -0,0 +1,73 @@
+Release v0.3 - September 17, 2009
+
+Release v0.3 adds some features, in particular LU and Cholesky decomposition,
+matrix exponentials, and random permutations. 
+
+Still no Mac OS X support, though :(
+
+
+Changes from version v0.2:
+
+- jar file can now contain dynamic as well as static files
+
+- added LAPACK functions [sdcz]geev, [sd]getrf, [sd]potrf
+
+- Added interfaces ConvertsToDoubleMatrix and ConverstToFloatMatrix
+
+- Added class Decompose which provides LUDecomposition (based on getrf),
+  and Cholesky decomposition (based on potrf)
+
+- Matrix classes: 
+  - Added read-only AbstractList views for elements, rows, and 
+    columns for better interfacing with Java's collection API. 
+  - Added matrix exponentials based on Pade approximation provided 
+    by Jan Saptra Müller. These should be pretty fast!
+  - Added prod() which returns the product of all elements.
+  - Added project() which projects one vector on another.
+  - Added diviRowVector().
+  - Added loadCSVFile().
+
+- Added MatrixFunctions.min() and .max() for integers.
+
+- Added Permutations class for generating random permutations and
+  subsets based on the algorithms from Knuth's "The Art of Computer
+  Programming", Vol. 2.
+
+
+----------------------------------------------------------------------
+
+Release v0.2 - May 8, 2009
+
+Release v0.2 mostly adds features to the build process and renames some
+packages and classes to make the structure simpler. No new significant
+functionality has been added.
+
+Changes from version v0.1:
+
+- fixed a bug in DoubleMatrix.copy()
+- Renamed packages to make structure simpler
+
+  org.jblas.la -> org.jblas
+  org.jblas.la.exceptions -> org.jblas.exceptions
+  org.jblas.la.ranges -> org.jblas.ranges
+  org.jblas.core -> moved content to org.jblas and org.jblas.util
+
+- Renamed classes
+
+  Blas -> NativeBlas
+
+- Build process can now generate different kinds of jar files, and also
+  generate shared libraries which are statically linked against BLAS,
+  LAPACK or ATLAS. You can also generate a multiplatform jar file which
+  contains shared libraries for different platforms.
+
+- Generated wrapper code has been optimized a bit:
+
+  - in the lapack wrapper with automatic workspace allocation, only
+    small dummy arrays are passed in the workspace query, meaning that
+    the real arrays are only passed once, not twice.
+
+  - The wrapper now also parses information whether output variables
+    are input or output and releases the arrays with JNI_ABORT in case
+    they are not output variables. This should also reduce the amount
+    of copying.
diff --git a/build.xml b/build.xml
index 98e5bba..aebae77 100644
--- a/build.xml
+++ b/build.xml
@@ -39,11 +39,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 		It also generates JavaDoc from source in ../doc.
     </description>
 
-	<!-- Define directories -->
+    <import file="configure.xml" />
+
+    <!-- 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="native-libs" value="${basedir}/native-libs" />
     <property name="doc" value="${basedir}/javadoc" />
     <property name="jar" value="${basedir}/jblas.jar" />
     <property name="include" value="${basedir}/include" />
@@ -51,8 +54,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     <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">
+    <property name="version" value="0.3" />
+
+    <!-- Macros -->
+
+    <macrodef name="class-to-float" description="generate a float version of a class">
         <attribute name="class"/>
         <attribute name="path" default="src"/>
         <sequential>
@@ -62,7 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
             </exec>
         </sequential>
     </macrodef>
-    <macrodef name="static-class-to-float">
+    <macrodef name="static-class-to-float" description="Add float versions to a class">
         <attribute name="class"/>
         <sequential>
             <echo message="Add float versions to class @{class}"/>
@@ -71,7 +77,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
             </exec>
         </sequential>
     </macrodef>
-    <macrodef name="rjpp">
+    <macrodef name="rjpp" description="Run the ruby-java preprocessor.">
         <attribute name="file"/>
         <sequential>
             <exec executable="ruby">
@@ -79,93 +85,146 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
             </exec>
         </sequential>
     </macrodef>
-    <target name="clean">
+    <macrodef name="create-jar" description="create jar file">
+        <attribute name="filename" />
+        <sequential>
+        <jar destfile="@{filename}">
+            <fileset dir="${bin}">
+                <include name="org/**" />
+                <include name="lib/**/lib*.so"/>
+                <include name="lib/**/*.dll"/>
+            </fileset>
+            <manifest>
+                <attribute name="Built-By" value="IDA Group, TU Berlin" />
+            </manifest>
+        </jar>
+        </sequential>
+    </macrodef>
+
+    <!-- Organizational targets -->
+
+    <target name="clean" description="clean generated files">
         <delete dir="${doc}" />
         <delete dir="${bin}" />
-        <delete dir="${native}" />
         <delete dir="${include}" />
-        <delete file="${jar}" />
-        <exec executable="make">
+        <exec executable="${make}">
             <arg line="clean" />
         </exec>
     </target>
-    <target name="realclean" depends="clean">
-        <exec executable="make">
+    <target name="clean-jars" description="delete all jar files">
+        <delete>
+            <fileset dir="." includes="*.jar" />
+        </delete>
+    </target>
+    <target name="realclean" depends="clean" description="delete also dumped information on fortran functions">
+        <exec executable="${make}">
             <arg line="realclean" />
         </exec>
     </target>
-    <target name="prepare">
+    <target name="prepare" description="create directories needed for compilation">
         <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">
+    <target name="compile" depends="prepare,wrapper,generate-float" description="compile java code">
+        <javac destdir="${bin}" encoding="utf-8" 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">
+    <target name="compile-test" depends="compile" description="compile java test code">
+        <javac destdir="${bin}" encoding="utf-8" 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">
+    <target name="javah" depends="prepare,wrapper,compile" description="run javah">
         <javah destdir="${include}" force="yes">
-            <class name="${pkgbase}.la.Blas" />
+            <class name="${pkgbase}.NativeBlas" />
             <classpath>
                 <pathelement path="${bin}" />
             </classpath>
         </javah>
     </target>
-    <target name="compile-native" depends="prepare,javah">
-        <exec executable="make">
+    <target name="compile-native" depends="prepare,javah" description="compile native JNI stubs">
+        <exec executable="${make}">
             <arg line="compile-native" />
         </exec>
     </target>
-    <target name="wrapper">
-        <exec executable="make">
+    <target name="wrapper" depends="prepare" description="generate the JNI stub code">
+        <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"/>
+    <target name="generate-float" depends="preprocess" description="generate float versions of classes">
+        <class-to-float class="${pkgbase}.DoubleMatrix"/>
+        <class-to-float class="${pkgbase}.DoubleFunction"/>
+        <class-to-float class="${pkgbase}.ComplexDouble"/>
+        <class-to-float path="test" class="${pkgbase}.TestDoubleMatrix"/>
+        <class-to-float path="test" class="${pkgbase}.TestBlasDouble"/>
+        <class-to-float class="${pkgbase}.ComplexDoubleMatrix"/>
+        <static-class-to-float class="${pkgbase}.SimpleBlas"/>
+        <static-class-to-float class="${pkgbase}.Solve"/>
+        <static-class-to-float class="${pkgbase}.Eigen"/>
+        <static-class-to-float class="${pkgbase}.Geometry"/>
+        <static-class-to-float class="${pkgbase}.MatrixFunctions"/>
+        <static-class-to-float class="${pkgbase}.JavaBlas"/>
+    </target>
+    <target name="preprocess" description="run the ruby preprocessor on necessary files">
+        <rjpp file="src/org/jblas/DoubleMatrix.java"/>
+        <rjpp file="test/org/jblas/TestDoubleMatrix.java"/>
+        <rjpp file="src/org/jblas/MatrixFunctions.java"/>
+        <rjpp file="src/org/jblas/ComplexDoubleMatrix.java"/>
+    </target>
+
+    <!-- jar files -->
+
+    <target name="jar" depends="compile,compile-native" description="create jblas.jar (local system, as configured)">
+        <delete dir="${bin}/lib" />
+        <copy todir="${bin}/lib">
+            <fileset dir="${native-libs}">
+                <include name="${linkage}/${os_name}/${os_arch}/*" />
             </fileset>
-            <manifest>
-                <attribute name="Built-By" value="IDA Group, TU Berlin" />
-            </manifest>
-        </jar>
+        </copy>
+        <create-jar filename="jblas-${version}.jar" />
+    </target>
+
+    <target name="dynamic-jar" depends="compile,compile-native" description="create jblas.jar (local system, dynamic)">
+        <delete dir="${bin}/lib" />
+        <copy todir="${bin}/lib">
+            <fileset dir="${native-libs}">
+                <include name="dynamic/${os_name}/${os_arch}/*" />
+            </fileset>
+        </copy>
+        <create-jar filename="jblas-${version}-${os_name}-${os_arch}.jar" />
     </target>
-    <target name="javadoc" depends="generate-float">
+    <target name="static-jar" description="create jblas-static.jar (local system, static)">
+        <delete dir="${bin}/lib" />
+        <copy todir="${bin}/lib">
+            <fileset dir="${native-libs}">
+                <include name="static/${os_name}/${os_arch}/*" />
+            </fileset>
+        </copy>
+        <create-jar filename="jblas-${version}-${os_name}-${os_arch}-static.jar" />
+    </target>
+    <target name="fat-jar" description="create jblas-multiplatform.jar (local system, static, plus everything else in native-libs)">
+        <delete dir="${bin}/lib" />
+        <copy todir="${bin}/lib">
+            <fileset dir="${native-libs}">
+                <include name="static/**" />
+            </fileset>
+        </copy>
+        <create-jar filename="jblas-${version}-multiplatform.jar" />
+    </target>
+    <target name="lean-jar" description="create jblas-lean.jar (local system, dynamic, without shared libs)" >
+        <delete dir="${bin}/lib" />
+        <create-jar filename="jblas-${version}-lean.jar" />
+    </target>
+
+    <!-- javadoc -->
+
+    <target name="javadoc" depends="generate-float,wrapper">
         <mkdir dir="${doc}" />
         <javadoc packagenames="org.jblas.*"
 		sourcepath="${src}" defaultexcludes="yes"
@@ -181,6 +240,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
             <tag name="dedication" scope="all" description="Dedication:" />
         </javadoc>
     </target>
+
+    <!-- testing -->
+
     <target name="test" depends="compile-test,jar">
         <junit printsummary="yes" haltonfailure="yes" showoutput="yes">
             <classpath>
@@ -188,14 +250,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                 <pathelement path="${bin}" />
             </classpath>
             <formatter type="plain" usefile="false" />
-            <test name="${pkgbase}.la.TestBlasDouble" />
+            <test name="${pkgbase}.TestDoubleMatrix" />
+            <test name="${pkgbase}.TestEigen" />
         </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}">
diff --git a/config/config.rb b/config/config.rb
index 618f2bb..1f20f1c 100644
--- a/config/config.rb
+++ b/config/config.rb
@@ -46,6 +46,7 @@ class Config
   def initialize
     @config = Hash.new {|h,k| Array.new }
     @log = open('configure.log', 'w')
+    @xmlstuff = Array.new
   end
 
   def [](k)
@@ -57,6 +58,17 @@ class Config
     log "Setting #{k} to #{v}"
   end
 
+  def add_xml(str)
+    @xmlstuff << str
+    return
+  end
+
+  def dump_xml(io)
+    io.puts "<project name=\"imported-configuration-settings\">"
+    io.puts(@xmlstuff.join "\n")
+    io.puts "</project>"
+  end
+
   def log(msg)
     @log.puts(msg)
   end
diff --git a/config/configure.rb b/config/configure.rb
index 2e9722d..1fe4b3c 100644
--- a/config/configure.rb
+++ b/config/configure.rb
@@ -70,13 +70,11 @@ config = Config.new
 # translate dir (mainly necessary for cygwin)
 def dir(s)
   case $os_name
-  when 'Linux'
-    s
-  when 'Windows XP'
-    s = s.gsub /\\/, '\\\\\\\\'
+  when 'Windows'
+    s = s.gsub(/\\/, '\\\\\\\\')
     %x(cygpath -u #{s}).chomp
   else
-    raise ConfigError, "The OS #{$os_name} is currently unsupported!"
+    s # safe default... 
   end
 end
 
@@ -87,7 +85,9 @@ def libname(name)
     case $os_name
     when 'Linux'
       'lib' + name + '.so'
-    when 'Windows XP'
+    when 'SunOS'
+      'lib' + name + '.so'
+    when 'Windows'
       'lib' + name + '.a'
     end
   end
@@ -96,7 +96,7 @@ 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}
+  %x(nm -p #{nmopt} #{fn}).grep(/ T _?([a-zA-Z0-9_]+)/) {|m| $1}
 end
 
 # indent a multiline text
@@ -104,6 +104,10 @@ class String
   def indent(cnt)
     split("\n").map {|l| ' ' * cnt + l}.join("\n")
   end
+
+  def start_with?(head)
+    self.length > head.length && self[0...head.length] == head
+  end
 end
 
 begin
@@ -122,14 +126,26 @@ begin
   ######################################################################
   config.msg('determining operating system') do
     $os_name = %x(java -cp config PrintProperty os.name).chomp
-    if $os_name == 'Windows XP'
+    if $os_name.start_with? 'Windows'
+      $os_name = 'Windows'
+    end
+    if $os_name == 'Windows'
       config.msg 'checking for cygpath' do
         config.check_cmd 'cygpath'
       end
     end
+    config['OS_NAME'] = $os_name
+    config.add_xml "<property name=\"os_name\" value=\"#{$os_name}\" />"
     $os_name
   end
 
+  config.msg('determining architecture') do
+    $os_arch = %x(java -cp config PrintProperty os.arch).chomp
+    config['OS_ARCH'] = $os_arch
+    config.add_xml "<property name=\"os_arch\" value=\"#{$os_arch}\" />"
+    $os_arch
+  end
+
   ######################################################################
   config.msg('locating the Java Development Kit') do
     $java_home = dir(File.dirname(%x(java -cp config PrintProperty java.home)))
@@ -143,10 +159,17 @@ begin
   config.msg('deciding whether to use g77 or gfortran') do
     g77 = where('g77')
     gfortran = where('gfortran')
+    f77 = where('f77')
     if g77
       config['LD'] = 'g77'
+      config['F77'] = 'g77'
     elsif gfortran
-      config['LD'] = 'gfortran'
+      #config['LD'] = 'gfortran'
+      config['F77'] = 'gfortran'
+      config['LD'] = 'gcc'
+    elsif f77
+      config['F77'] = 'f77'
+      config['LD'] = 'f77'
     else
       config.fail <<EOS.indent 2
 Either g77 or gfortran have to be installed to compile against the
@@ -162,14 +185,24 @@ EOS
     when 'Linux'
       config << <<EOS
 CC = gcc
-CFLAGS = -fPIC -ggdb
+CFLAGS = -fPIC
 INCDIRS += -Iinclude -I#{$java_home}/include -I#{$java_home}/include/linux
 SO = so
 LIB = lib
 RUBY=ruby
 LDFLAGS += -shared
 EOS
-    when 'Windows XP'
+    when 'SunOS'
+      config << <<EOS
+CC = gcc
+CFLAGS = -fPIC
+INCDIRS += -Iinclude -I#{$java_home}/include -I#{$java_home}/include/solaris
+SO = so
+LIB = lib
+RUBY=ruby
+LDFLAGS += -G
+EOS
+    when 'Windows'
       config.check_cmd('cygpath')
       config << <<EOS
 CC = gcc
@@ -186,6 +219,21 @@ EOS
   end
 
   ######################################################################
+  config.msg('looking for version of make') do
+     if where('gmake')
+	puts 'gmake'
+        config['MAKE'] = 'gmake'
+	config.add_xml '<property name="make" value="gmake" />'
+     else
+        if where_with_output('make -v', /GNU Make/).nil?
+      	  config.fail('I need GNU make to run...')
+	end
+        config['MAKE'] = 'make'
+	config.add_xml '<property name="make" value="make" />'
+     end
+  end
+
+  ######################################################################
   def check_lapack_home(config)
     config.check_files($lapack_home, 
                        ['BLAS', 'SRC', 'dgemm.f'], 
@@ -201,7 +249,8 @@ EOS
     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'))
+        lapack_tgz = File.join('.', 'lapack-lite-3.1.1.tgz')
+        File.delete(lapack_tgz) if File.exist?(lapack_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)
@@ -338,7 +387,19 @@ EOS
       nil
     end
   end
-  
+
+  ######################################################################
+  #
+  # Set output directory depending on static or dynamic libraries
+  #
+  if $opts.defined? :static_libs
+    config.add_xml '<property name="linkage" value="static" />'
+    config['LINKAGE'] = 'static'
+  else
+    config.add_xml '<property name="linkage" value="dynamic" />'
+    config['LINKAGE'] = 'dynamic'
+  end
+
 
   ######################################################################
   # Some sanity checks, in particular that ATLAS's and LAPACK's lapack
@@ -355,23 +416,32 @@ EOS
   end
 
   # Okay, then we're done!
+  config << "LDFLAGS += #{$libpaths.map {|s| '-L' + s}.join ' '}"
+
   if $opts.defined? :lapack_build
-    config << <<EOS
-LDFLAGS += #{$libpaths.map {|s| '-L' + s}.join ' '}
-LOADLIBES = -l#{$lapack_name} -l#{$blas_name}
-EOS
+    loadlibes = [$lapack_name, $blas_name]
   else
-    config << <<EOS
-LDFLAGS += #{$libpaths.map {|s| '-L' + s}.join ' '}
-LOADLIBES = -l#{$lapack_atlas_name} -l#{$lapack_name} -l#{$blas_name} -lcblas -latlas
-EOS
+    loadlibes = [$lapack_atlas_name, $lapack_name, $blas_name, 'cblas', 'atlas']
+  end
+
+  if $opts.defined? :static_libs
+    loadlibes = "LOADLIBES = -Wl,--allow-multiple-definition #{loadlibes.map {|l| ' -l:lib' + l + '.a'}}"
+  else
+    loadlibes = "LOADLIBES =#{loadlibes.map {|l| ' -l' + l}}"
+  end
+
+  # add fortran static library if we're using gfortran
+  if $opts.defined? :static_libs and config['F77'] == 'gfortran'
+    loadlibes += " -l:libgfortran.a"
   end
+  config << loadlibes
 
   ######################################################################
   # dumping results
   puts
   puts 'Configuration succesfull, writing out results to configure.out'
   open('configure.out', 'w') {|f| config.dump f}
+  open('configure.xml', 'w') {|f| config.dump_xml f}
 
 rescue ConfigError => e
   puts 
diff --git a/config/path.rb b/config/path.rb
index 85b0b3f..febeab3 100644
--- a/config/path.rb
+++ b/config/path.rb
@@ -53,3 +53,18 @@ def where(file, path=PATH)
   end
   return
 end
+
+# returns the path to the command as specified by
+# line or nil if the command does not exist, or
+# it did not produce the right result
+def where_with_output(line, output)
+   cmd = line.split[0]
+   p = where(cmd)
+   return unless p
+   out = %x(#{File.join(p,line)})
+   if out =~ output
+     return p
+   else
+     return
+   end
+end
diff --git a/configure b/configure
index 86c95a9..49cca94 100755
--- a/configure
+++ b/configure
@@ -1,4 +1,10 @@
-#!/bin/sh
+#!/bin/bash
+
+if [ "$1" == "--keep-options" ]; then
+    shift
+else
+    echo $* >configure.options
+fi
 
 ruby config/configure.rb $*
 
diff --git a/docs/jblas-logo.png b/docs/jblas-logo.png
new file mode 100644
index 0000000..a089040
Binary files /dev/null and b/docs/jblas-logo.png differ
diff --git a/docs/jblas-logo.svg b/docs/jblas-logo.svg
new file mode 100644
index 0000000..57a6066
--- /dev/null
+++ b/docs/jblas-logo.svg
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="189.63225"
+   height="86.328003"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   version="1.0"
+   sodipodi:docname="jblas-logo.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/mikio/workspace/Java-Blas/docs/jblas-logo.png"
+   inkscape:export-xdpi="75"
+   inkscape:export-ydpi="75">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="107.07615"
+     inkscape:cy="16.384286"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="1127"
+     inkscape:window-x="0"
+     inkscape:window-y="25" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-148.88915,-142.97361)">
+    <text
+       xml:space="preserve"
+       style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#0b0b28;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Bookman L;-inkscape-font-specification:URW Bookman L"
+       x="162.85715"
+       y="200.93361"
+       id="text2383"><tspan
+         sodipodi:role="line"
+         id="tspan2385"
+         x="162.85715"
+         y="200.93361"><tspan
+   style="fill:#ff6600"
+   id="tspan2415">j</tspan>blas</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Bookman L;-inkscape-font-specification:URW Bookman L"
+       x="620"
+       y="426.64789"
+       id="text2387"><tspan
+         sodipodi:role="line"
+         id="tspan2389"
+         x="620"
+         y="426.64789" /></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ff6600;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Bookman L;-inkscape-font-specification:URW Bookman L"
+       x="181.87302"
+       y="215.72533"
+       id="text2391"><tspan
+         sodipodi:role="line"
+         id="tspan2393"
+         x="181.87302"
+         y="215.72533"
+         style="font-size:13px;fill:#ff6600">Linear Algebra for Java</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Bookman L;-inkscape-font-specification:URW Bookman L"
+       x="177"
+       y="225.328"
+       id="text2417"
+       transform="translate(148.88915,142.97361)"><tspan
+         sodipodi:role="line"
+         id="tspan2419"
+         x="177"
+         y="225.328" /></text>
+  </g>
+</svg>
diff --git a/docs/jblas-thumb.png b/docs/jblas-thumb.png
new file mode 100644
index 0000000..4e2b1b7
Binary files /dev/null and b/docs/jblas-thumb.png differ
diff --git a/docs/render.rb b/docs/render.rb
new file mode 100644
index 0000000..3621506
--- /dev/null
+++ b/docs/render.rb
@@ -0,0 +1,10 @@
+require 'rubygems'
+require 'redcloth'
+
+ARGV.each do |f|
+  newf = f.gsub /.textile$/, '.html'
+  out = open(newf, 'w') do |o|
+    txt = open(f, 'r').read
+    o.write RedCloth.new(txt).to_html
+  end
+end
diff --git a/docs/tutorial.textile b/docs/tutorial.textile
new file mode 100644
index 0000000..3a7d6fd
--- /dev/null
+++ b/docs/tutorial.textile
@@ -0,0 +1,111 @@
+h1. JBLAS Tutorial
+
+<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>
+
+h2. An Example
+
+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. Since Java does not support operator overloading (like C++, for example), some work is required, though.
+
+For example, the formula
+
+<pre>
+    y = A * x + c
+</pre>
+
+is translated to (leaving declarations aside)
+
+<pre>
+    y = A.mmul(x).add(c)
+</pre>
+
+In other words, each binary operator like +, or * is translated to a method. This allows to keep the structure of the expression very similar to the original formula.
+
+JBLAS currently supports real and complex matrices in single and double precision. These matrices currently exist next to each other with little infrastructure to mix these matrices in a computation. This is certainly the next step, but for the first version it felt like too much of an overhead, in particular because you usually pick one kind of precision and stick to it.
+
+h2. Classes Overview
+
+The same holds for sparse matrices, and other special storage scheme. JBLAS may not be as feature rich as other packages, but what you get covers most of your applications, and it is really fast (and we think it's pretty convient, too!)
+
+The following four classes exist
+
+|_.Class |_.Number Type |_.Precision |
+|FloatMatrix | real | single precision |
+|DoubleMatrix | real | double precision |
+|ComplexFloatMatrix | complex | single precision |
+|ComplexDoubleMatrix | complex | double precision |
+
+Apart from these Matrix classes, there exist special classes for complex numbers, namely @ComplexFloat@ and @ComplexDouble@ in the @edu.ida.???@ package.
+
+Special routines for computing eigenvalues, or solving linear equations are collected as static members in the following classes:
+
+|_.Class |_.Description|
+|Eigen|eigenproblems|
+|Solve|linear equations|
+|Geometry|geometric computations|
+
+h2. Some Design Decisions
+
+Before we'll finally start to work with some matrices, 
+
+* *Only two-dimensional matrices* This library was planned to be closely tied to BLAS and LAPACK which only support two-dimensional matrices. Therefore, JBLAS only supports two-dimensional matrices.
+* *No difference between vectors and matrices* There is no distinction between vectors and matrices.
+* *In-place Operations* Having support for in-place operations was crucial.
+* *Scalars* Single-element matrices behave like scalars.
+
+h2. Constructing Matrices
+
+Okay, now that we have covered the broad structure of JBLAS, let's discuss how to actually construct a matrix.
+
+h2. Arithmetics
+
+If you peek a look at the documentation of a class like @DoubleMatrix@, you'll at first be overwhelmed by the large number of methods available. However, as we'll shortly discuss, most of these methods are overloads which exist for the sake of convenience. For example, if you want to add two matrices, you can always use the @add@ method, irrespective of whether your adding matrices, vectors, scalars, or primitve double values.
+
+The other factor comes from the support of variants for in-place computation. For example, by adding an "i" to a method you can often get an in-place version. To subtract to vectors in-place, you use @subi at . This again adds a few more overloaded functions, but the general scheme is quite simple.
+
+Maybe the best metaphor is to think in terms of an assembly language where you can also add small little modifiers to mnemonics to do different things.
+
+h3. Basic Arithmetic Operations
+
+h3. In-place Computations
+
+Java's use of a garbage collector is quite convenient, but can really kill your performance with matrix computations. The problem is that every computation generates a new object which will eventually gets recycled, but object construction takes some time. The situation is different from C++, where ideally, the compiler can precompute how many temporary objects it needs and keep that number fixed.
+
+Therefore, most operations can be carried out in-place, where the receiver of the method will hold the final result.
+
+For example,
+
+<pre>
+  x.add(y)
+</pre>
+
+generates a new object, but
+
+<pre>
+  x.addi(y)
+</pre>
+
+basically computes @x += y@, storing the result in @x at .
+
+If you want, you can also supply the matrix holding the result as a third argument:
+
+<pre>
+   x.addi(y, z)
+</pre>
+
+which computes @z = x + y@ without generating a new object.
+
+In all of the in-place computation, the result object is required to have the correct dimension before you call the method!
+
+h3. Elementwise Computations, Vectors and Scalars
+
+h2. Linear Algebra Computations
+
+The already implemented linear algebra routines cover the basic computations only at the moment. LAPACK consists virtually thousands of such functions, but I haven't yet gotten around to wrapping them automatically. Therefore, I'm doing this by hand at the moment and are adding functions as I need them.
+
+If you really need some function, don't hestitate to contact me, preferably with an example of how to use the function. The problem is that there are so many routines in LAPACK that I really can't know what each of them is supposed to do. So I'd happily add a wrapper for you, but you must help me making it run.
+
+That said, here is an overview of what currently exists.
+
+h2. Some Background on the Implementation
+
+[The issue with DirectBuffers]
diff --git a/examples/complex.rb b/examples/complex.rb
new file mode 100644
index 0000000..40df776
--- /dev/null
+++ b/examples/complex.rb
@@ -0,0 +1,47 @@
+# This file demonstrates how to access a java file contained in a
+# jar file, how to extend the java object and make a numeric
+# class interact seamlessly with normal ruby numeric objects
+
+# load the jar file
+require '../jBLAS.jar'
+
+# We provide a short-cut for the class com.fhg.core.DoubleComplex
+DoubleComplex = Java::edu.ida.core.DoubleComplex
+
+# we extend the class
+class DoubleComplex
+  # add operators
+  def +(o); add(promote(o)); end
+  def -(o); sub(promote(o)); end
+  def *(o); mul(promote(o)); end
+  def /(o); div(promote(o)); end
+
+  # extend the range of the operators to also deal with
+  # non-complex numeric arguments
+  def promote(o)
+    if Numeric === o
+      DoubleComplex.new(o, 0)
+    else
+      o
+    end
+  end
+
+  # make sure that it also works when the left hand side operator
+  # is not a double
+  def coerce(o)
+    unless DoubleComplex === o
+      [self, o]
+    end
+  end
+
+  # to make sure that we look pretty in irb
+  def inspect
+    toString
+  end
+end
+
+# imaginary number
+I = DoubleComplex.new(0, 1)
+
+# and voila, it works!
+puts (1 + 3*I)/ 2*I
diff --git a/examples/jmatrix.rb b/examples/jmatrix.rb
new file mode 100644
index 0000000..1d4d550
--- /dev/null
+++ b/examples/jmatrix.rb
@@ -0,0 +1,183 @@
+# This file contains a very unfinished sketch of how you can use the matrix
+# classes from jruby. Note that we make heavy use of ruby's ability to extend
+# existing classes, for example, in order to devine arithmetic operators for
+# the matrix classes.
+require 'java'
+require '../jBLAS.jar'
+
+module JBLAS
+  include Java
+  import 'edu.ida.la.DoubleMatrix'
+  import 'edu.ida.la.FloatMatrix'
+  import 'edu.ida.la.DoubleVector'
+  import 'edu.ida.la.FloatVector'
+  import 'edu.ida.la.SimpleBlas'
+  import 'edu.ida.la.DoubleFunction'
+  import 'edu.ida.la.FloatFunction'
+  
+  import 'edu.ida.la.Solve'
+  import 'edu.ida.la.Eigen'
+  import 'edu.ida.la.Geometry'
+
+  # This module contains the matrix object extensions which will later be mixed-in
+  # to DoubleMatrix and FloatMatrix. This safes us from unnecessary code
+  # duplication.
+  module MatrixExt
+    def [](i, j)
+      get(i, j)
+    end
+    
+    def []=(i, j, v)
+      put(i, j, v)
+    end
+    
+    def +(o); add(o); end
+    def -(o); sub(o); end
+    def *(o); mul(o); end
+    
+    def coerce(o)
+      unless self.class === o
+        [self, o]
+      end
+    end
+    
+    def t; transpose; end
+  end
+  
+  module MatrixStaticExt
+    def [](*data)
+      n = data.length
+      if data.reject{|l| Numeric === l}.size == 0
+        a = self.new(1, n)
+        (0...data.length).each do |i|
+          a[0, i] = data[i]
+        end
+        return a
+      else
+        begin
+          lengths = data.collect{|v| v.length}
+        rescue
+          raise "All columns must be arrays"
+        end
+        raise "All columns must have equal length!" if lengths.min < lengths.max
+        a = self.new(n, lengths.max)
+        for i in 0...n
+          for j in 0...lengths.max
+            a[i,j] = data[i][j]
+          end
+        end
+        return a
+      end
+    end
+  end
+
+  # Extend the matrix classes with the functionalities defined above. 
+  class DoubleMatrix
+    class << self
+      include MatrixStaticExt
+    end
+    include MatrixExt
+  end
+  
+  class FloatMatrix
+    class << self
+      include MatrixStaticExt
+    end
+    include MatrixExt
+  end
+
+  # Double Vector and Float Vector, fully spelled out this time.
+  class DoubleVector
+    def [](i); get(i); end
+    
+    def []=(i, v); put(i, v); end
+    
+    def +(o); add(o); end
+    def -(o); sub(o); end
+    def *(o); mul(o); end
+    
+    def self.[](*data)
+      a = self.new(data.length)
+      for i in (0...data.length)
+        a[i] = data[i].to_f
+      end
+      return a
+    end
+    
+    def coerce(o)
+      unless self.class === o
+        [self, o]
+      end
+    end
+    
+    def to_s
+      "[" + toString.gsub(/\t/, ', ') + "]"
+    end
+    
+    class Fct
+      include DoubleFunction
+      
+      def initialize(block)
+        @block = block
+      end
+      
+      def compute(x)
+        @block.call(x)
+      end
+    end
+    
+    alias java_map map
+
+    # a slightly more rubyesque map function which takes a block
+    def map(&block)
+      java_map(Fct.new block)
+    end
+  end
+
+  class FloatVector
+    def [](i); get(i); end
+    
+    def []=(i, v); put(i, v); end
+    
+    def +(o); add(o); end
+    def -(o); sub(o); end
+    def *(o); mul(o); end
+    
+    def self.[](*data)
+      a = self.new(data.length)
+      for i in (0...data.length)
+        a[i] = data[i].to_f
+      end
+      return a
+    end
+    
+    def coerce(o)
+      unless self.class === o
+        [self, o]
+      end
+    end
+    
+    def to_s
+      "[" + toString.gsub(/\t/, ', ') + "]"
+    end
+    
+    class Fct
+      include FloatFunction
+      
+      def initialize(block)
+        @block = block
+      end
+      
+      def compute(x)
+        @block.call(x)
+      end
+    end
+    
+    alias java_map map
+
+    # a slightly more rubyesque map function which takes a block
+    def map(&block)
+      java_map(Fct.new block)
+    end
+  end
+end
diff --git a/examples/test_abitofml.rb b/examples/test_abitofml.rb
new file mode 100644
index 0000000..e05154d
--- /dev/null
+++ b/examples/test_abitofml.rb
@@ -0,0 +1,118 @@
+require 'test/unit'
+require 'jmatrix'
+require 'tictoc'
+
+include JBLAS
+
+import 'edu.ida.la.Solve'
+import 'edu.ida.la.Eigen'
+import 'edu.ida.la.Geometry'
+
+#
+# Radial Basis Function Kernel
+#
+class RbfKern
+  def initialize(width)
+    @width = width
+  end
+
+  def [](x, y=nil)
+    #puts "upsi"
+    if not y
+      y = x
+    end
+
+    Geometry.pairwiseSquaredDistances(x, y).muli(-1.0/(2.0*@width)).expi()
+  end
+end
+
+def normalize_mse(yhat, y)
+  (y - yhat).norm2 / (y - y.mean).norm2
+end
+
+class KRR
+  def initialize(kernel)
+    @kernel = kernel
+  end
+
+  def train(tau, x, y)
+    n = y.length
+    tic "Setting up kernel matrix"
+    k = @kernel[x]
+    toc
+    tic "Computing alpha (sysv)"
+    @alpha = Solve.solveSymmetric(k + tau * k.class.eye(n), y)
+    toc
+    tic "Computing alpha (posv)"
+    @alpha = Solve.solvePositive(k + tau * k.class.eye(n), y)
+    toc
+    
+    tic "computing eigenvalues"
+    ev = Eigen.symmetricEigenvalues(k)
+    toc
+
+    tic "computing eigenvectors and eigenvalues"
+    ev = Eigen.symmetricEigenvectors(k)
+    toc
+    
+    puts ev
+    if n < 50
+      puts ev[0]
+      puts 
+      puts ev[1]
+    end 
+
+    @trainX = x
+  end
+
+  def [](x)
+    tic "Setting up kernel matrix for prediction"
+    k = @kernel[x, @trainX]
+    toc
+    tic "Predicting"
+    yhat = k * @alpha
+    toc
+    return yhat
+  end
+end
+
+
+class ABitOfML < Test::Unit::TestCase
+  def krr_on_sinc(n, vec, ext)
+    
+    tic "Generating the data..."
+    #x = 8 * vec.rand(n).sort - 4
+    x = 8 * vec.rand(n) - 4
+    s = x.sinc()
+    y = s + vec.randn(n) * 0.1
+    toc
+
+    krr = KRR.new(RbfKern.new 1.0)
+    krr.train(1e-3, x, y)
+    yhat = krr[x]
+
+    fit_error = normalize_mse(yhat, y)
+    
+    puts "Fit error #{fit_error}"
+
+    assert_in_delta(0.3, fit_error, 0.1)
+
+    #
+    # generate a matlab script to plot the result
+    #
+    open("sincdemo_#{ext}.m", "w") do |o|
+      o.write "X = #{x};"
+      o.write "Y = #{y};"
+      o.write "Yhat = #{yhat};"
+      o.write "plot(X, Y, '.', X, Yhat, 'r-', 'LineWidth', 5);"
+    end
+  end
+
+  def test_double
+    krr_on_sinc(1000, DoubleVector, 'double')
+  end
+
+  def test_float
+    krr_on_sinc(1000, FloatVector, 'float')
+  end
+end
diff --git a/examples/test_matrix.rb b/examples/test_matrix.rb
new file mode 100644
index 0000000..5ca8270
--- /dev/null
+++ b/examples/test_matrix.rb
@@ -0,0 +1,96 @@
+require 'test/unit'
+require 'jmatrix.rb'
+require 'tictoc.rb'
+
+include JBLAS
+
+class TestMatrix < Test::Unit::TestCase
+  def run_some_tests(mat,vec)
+    # construct 3 * 3 matrix and fill in some values
+    a = mat.new(3,3)
+    for i in 0..2
+      for j in 0..2
+        a[i,j] = i + j
+      end
+    end
+    
+    puts a
+    
+    # construct a matrix from nested arrays
+    x = mat[[1], [2], [3]]
+    a = mat[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
+    
+    puts x
+    puts a
+    
+    # normal arithmetics work
+    puts (y = a * vec[1, 2, 3])
+    
+    # elementwise exponential
+    puts vec[1,2,3].exp
+    
+  
+    # elementwise exponential on a long vector
+    z = vec[*(0..10000).to_a]
+    tic "applying exp to the whole matrix"
+    x = z.dup.map {|x| Math.exp(x)}
+    toc
+    
+    tic "the same in Java"
+    x = z.dup.exp
+    toc
+    
+    # computing norms
+    puts "y = #{y}"
+    puts "2-norm of y = #{y.norm2}"
+    puts "1-norm of y = #{y.norm1}"
+    puts "maximum norm of y = #{y.maxnorm}"
+    
+    puts "converting a vector to an array"
+    puts y.to_array
+    puts a.to_array
+    
+    # a big matrix
+    n = 1000
+    puts "filling #{n} * #{n} matrix"
+    m = mat.new(n, n)
+    for i in 0...10
+      for j in 0...n
+    m[i,j] = rand
+      end
+    end
+    
+    puts "Multiplying with itself"
+    
+    5.times do 
+      tic "Timing"
+      c = m * m
+      toc
+    end
+    
+    # rank one update
+    x = vec.rand(1000)
+    
+    5.times do
+      tic "Rank one update with xGER       "
+      c = m.rank_one_update(x)
+      toc
+      tic "using explicit matrix operations"
+      c = m + x.as_column_vector * x.as_row_vector
+      toc
+    end
+    
+    tic "compared to matrix - vector multiplication"
+    c = m * x
+    toc
+    
+  end
+
+  def test_double
+    run_some_tests(DoubleMatrix, DoubleVector)
+  end
+
+  def test_float
+    run_some_tests(FloatMatrix, FloatVector)
+  end
+end
diff --git a/examples/test_time_eigen.rb b/examples/test_time_eigen.rb
new file mode 100644
index 0000000..7eedcd1
--- /dev/null
+++ b/examples/test_time_eigen.rb
@@ -0,0 +1,35 @@
+require 'tictoc'
+require 'jmatrix'
+require 'benchmark'
+
+include JBLAS
+
+def char(s)
+  case s
+  when String
+    java.lang.Character.new(s[0])
+  when Fixnum
+    java.lang.Character.new(s)
+  end
+end
+
+n = 1000
+
+def time_it(n, i)
+  x = DoubleVector.randn(n).sort
+  k = Geometry.pairwiseSquaredDistances(x, x).muli(-2).expi
+  ev = DoubleVector.new(n)
+
+  puts "Benchmark for n = #{n} (reported numbers are #{i} iterations)"
+
+  Benchmark.benchmark do |r|
+    r.report("syev eigenvalues:  ") { i.times { SimpleBlas.syev(char('N'), char('U'), k.dup, ev) } }    
+    r.report("syevd eigenvalues: ") { i.times { SimpleBlas.syevd(char('N'), char('U'), k.dup, ev) } }    
+    r.report("syev eigenvectors: ") { i.times { SimpleBlas.syev(char('V'), char('U'), k.dup, ev) } }    
+    r.report("syevd eigenvectors:") { i.times { SimpleBlas.syevd(char('V'), char('U'), k.dup, ev) } }    
+  end
+end
+
+time_it(100, 100)
+time_it(500, 20)
+time_it(1000, 5)
\ No newline at end of file
diff --git a/examples/tictoc.rb b/examples/tictoc.rb
new file mode 100644
index 0000000..de3cc67
--- /dev/null
+++ b/examples/tictoc.rb
@@ -0,0 +1,33 @@
+# some tools for timing code
+#
+# Either used as
+#
+#    tic
+#    do something...
+#    tic
+#
+# or as a block
+#
+#    tictoc do 
+#      do something...
+#    end
+#
+# The non-block one might be more handy if you define new variables in your code.
+
+def tic(message=nil)
+  if message
+    print message + "... "
+    $stdout.flush
+  end
+  $saved_time = Time.new
+end
+
+def toc
+  print "(#{Time.new - $saved_time} seconds)\n"
+end
+
+def tictoc(message=nil)
+  tic message
+  yield
+  toc
+end
diff --git a/fortranwrapper.dump b/fortranwrapper.dump
index 98e79c2..09c16f4 100644
Binary files a/fortranwrapper.dump and b/fortranwrapper.dump differ
diff --git a/nbproject/project.xml b/nbproject/project.xml
index 33deba3..2768776 100644
--- a/nbproject/project.xml
+++ b/nbproject/project.xml
@@ -50,6 +50,13 @@
                     <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
                     <encoding>UTF-8</encoding>
                 </source-folder>
+                <source-folder>
+                    <label>config</label>
+                    <type>java</type>
+                    <location>config</location>
+                    <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+                    <encoding>UTF-8</encoding>
+                </source-folder>
             </folders>
             <ide-actions>
                 <action name="build">
@@ -110,7 +117,7 @@
             </ide-actions>
             <export>
                 <type>jar</type>
-                <location>jBLAS.jar</location>
+                <location>jblas.jar</location>
                 <build-target>jar</build-target>
             </export>
             <view>
@@ -140,6 +147,11 @@
                         <location>include</location>
                         <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
                     </source-folder>
+                    <source-folder style="packages">
+                        <label>config</label>
+                        <location>config</location>
+                        <excludes>**/doc/,**/*.rjpp,**/*.cache</excludes>
+                    </source-folder>
                     <source-file>
                         <location>build.xml</location>
                     </source-file>
@@ -157,7 +169,7 @@
         <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>
+                <built-to>jblas.jar</built-to>
                 <source-level>1.5</source-level>
             </compilation-unit>
             <compilation-unit>
@@ -178,6 +190,10 @@
                 <package-root>include</package-root>
                 <source-level>1.5</source-level>
             </compilation-unit>
+            <compilation-unit>
+                <package-root>config</package-root>
+                <source-level>1.5</source-level>
+            </compilation-unit>
         </java-data>
     </configuration>
 </project>
diff --git a/scripts/class_to_float.rb b/scripts/class_to_float.rb
index 43ce5bd..5d3c8f8 100644
--- a/scripts/class_to_float.rb
+++ b/scripts/class_to_float.rb
@@ -54,15 +54,17 @@ def translate(s)
   s.gsub! /DoubleBuffer/, 'FloatBuffer'
   s.gsub! /DoubleVector/, 'FloatVector'
   s.gsub! /ComplexDouble/, 'ComplexFloat'
-  s.gsub! /([0-9]+\.[0-9]+)/, '\1f'
+  s.gsub! /([0-9]+\.[0-9]+(?:[eE]-?[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! /(\s)NativeBlas\.dz/, '\1NativeBlas.sc'
+  s.gsub! /(\s)NativeBlas\.d/, '\1NativeBlas.s'
+  s.gsub! /(\s)NativeBlas\.z/, '\1NativeBlas.c'
   s.gsub! /nextDouble/, 'nextFloat'
   s.gsub! /DoubleFunction/, 'FloatFunction'
   s.gsub! /TestBlasDouble/, 'TestBlasFloat'
   s.gsub! /Double\./, 'Float.'
+  s.gsub! /(\s)Double(\s)/, '\1Float\1'
+  s.gsub! /<Double>/, '<Float>'
   s.gsub! /readDouble/, 'readFloat'
   s
 end
diff --git a/scripts/fortran/c.rb b/scripts/fortran/c.rb
deleted file mode 100644
index 35a952b..0000000
--- a/scripts/fortran/c.rb
+++ /dev/null
@@ -1,175 +0,0 @@
-## --- 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
index 184b2ea..448a3cf 100644
--- a/scripts/fortran/java.rb
+++ b/scripts/fortran/java.rb
@@ -32,6 +32,28 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ## --- END LICENSE BLOCK ---
 
+# This function contains the code to generate both Java and C wrapper
+# classes for the JNI between Java and the Fortran code.
+#
+# The main entry point is the class Generator which can be used
+# together with templates to generate the code for all routines.
+# 
+# The Generator class in turn constructs a WrapperCodeGenerator object
+# which constructs the code for a single routine. Unfortunately, the
+# code here is rather unwieldy and is a prime goal for refactoring.
+#
+# Suffice to say that some things like the java wrapper code and the
+# automatic workspace methods are generated in one function (namely
+# native_declaration and with_workspace_query).
+#
+# Generation of the C wrapper code is much more involved,
+# unfortunately, in particular because I chose to write some fairly
+# complex OO-style code. Basically, ther exists a GenericArgument or
+# derived class for each type of object which overloads the different
+# parts of the wrapper code.
+
+require 'template_context'
+
 module Fortran
 
   class FortranType
@@ -153,6 +175,7 @@ module Fortran
       attr_accessor :fortran_args, :fortran_return_type
       attr_accessor :conversions
       attr_accessor :call_pre, :call_post, :fortran_fct_name, :call_args
+      attr_accessor :release_arrays
       attr_accessor :arrays
       
       def initialize(prefix, r)
@@ -168,6 +191,7 @@ module Fortran
         @fortran_fct_name = ''
         @call_args = []
         @call_post = ''
+        @release_arrays = ''
         @arrays = [] # already seen arrays
       end
       
@@ -180,10 +204,24 @@ module Fortran
 
         code_for_return_type(r.return_type)
 
-        r.each_arg do |name, type| 
+        r.each_arg do |name, type|
           code_for_argument(name, type)
         end
 
+        # first we generate the code for the non-output arguments
+        r.each_arg do |name, type|
+          if not type.output?
+            code_for_array_management(name, type)
+          end
+        end
+
+        # and now for the output arguments
+        r.each_arg do |name, type|
+          if type.output?
+            code_for_array_management(name, type)
+          end
+        end
+
         return <<EOS
 JNIEXPORT #{return_type} JNICALL Java_#{fct_name}(JNIEnv *env, jclass this#{decl_args})
 {
@@ -192,13 +230,15 @@ JNIEXPORT #{return_type} JNICALL Java_#{fct_name}(JNIEnv *env, jclass this#{decl
 #{conversions}
   savedEnv = env;
   #{call_pre}#{fortran_fct_name}(#{call_args.join(', ')});
-#{call_post}
+#{release_arrays}#{call_post}
 }
 EOS
       end
       
+      ######################################################################
       # Generate the native function declaration within a Java class.
-      # Everything you need is HERE!
+      # Unlike the Java version, which is a bit over-engineered, EVERYTHING
+      # YOU NEED IS HERE!
       def native_declaration
         begin
           return_type = ''
@@ -228,7 +268,11 @@ EOS
           raise
         end
       end
+      #
+      # That's it ;)
+      ########################################################################
 
+      ######################################################################
       # Generate Java function with an automatic workspace query.
       def with_workspace_query
         args = []
@@ -253,11 +297,14 @@ EOS
   }
 EOS
       end
+      # That's it
+      ######################################################################
+
+      def r; @routine; end
 
   private ############################################################
 
       # convenience accessor
-      def r; @routine; end
 
       def java_return_type
           if r.return_type.basetype == 'VOID' and r.args.last == 'INFO'
@@ -295,12 +342,23 @@ EOS
 
         gen.make_decl_arg
         gen.make_fortran_arg
-        gen.make_convert_arg
         gen.make_call_arg
       end
 
+      def code_for_array_management(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_convert_arg
+      end
+
       # find the correct code generator for the given type
-      def generator(type, name=nil)       
+      def generator(type, name=nil)    
         javatype = type.to_java
         #puts javatype
         #puts name
@@ -348,7 +406,10 @@ EOS
                 if r.workspace_argument? n
                   "#{n.downcase}, 0"
                 else
-                  "#{n.downcase}, #{n.downcase}Idx"
+                  # replace array arguments by their type
+                  dummy_name = t.to_java.gsub /\[\]/, 'Dummy'
+                  #"#{t.to_java} #{n.downcase}, #{n.downcase}Idx"
+                  "#{dummy_name}, 0"
                 end
               else
                 n.downcase
@@ -391,6 +452,7 @@ EOS
     # 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 
@@ -451,6 +513,7 @@ EOS
       end
     end
 
+    #----------------------------------------------------------------------
     # For arrays: Add an additional argument to the declaration,
     # and get the array from the direct buffer
     class BufferArgument < GenericArgument
@@ -489,19 +552,20 @@ EOS
 EOS
         
         # and releasing the stuff again...
-        release = "  if(#{name}PtrBase"
-        code.arrays.each do |a, t| 
+        release = []
+        release << "  if(#{name}PtrBase) {"
+        release << "    (*env)->Release#{basectype[1..-1].capitalize}ArrayElements(env, #{name}, #{name}PtrBase, #{@type.output? ? '0' : 'JNI_ABORT'});"
+        code.arrays.each do |a, t|
           if t == basectype
-            release << " && #{name}PtrBase != #{a}PtrBase"
+            release << "    if (#{name}PtrBase == #{a}PtrBase)"
+            release << "      #{a}PtrBase = 0;"
           end
         end
-        release << ") {" + <<EOS
-        
-    (*env)->Release#{basectype[1..-1].capitalize}ArrayElements(env, #{name}, #{name}PtrBase, 0);
-  }
-EOS
-        code.call_post = release + code.call_post
-        
+        release << "    #{name}PtrBase = 0;"
+        release << "  }\n"
+
+        code.release_arrays = release.join("\n") + code.release_arrays
+                   
         # store information about the arrays we have already handled
         code.arrays << [name, basectype]
       end
@@ -511,6 +575,7 @@ EOS
       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.
@@ -545,6 +610,7 @@ EOS
       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
@@ -561,12 +627,14 @@ EOS
       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
diff --git a/scripts/fortran.rb b/scripts/fortran/parser.rb
similarity index 50%
rename from scripts/fortran.rb
rename to scripts/fortran/parser.rb
index eef9028..ea24024 100644
--- a/scripts/fortran.rb
+++ b/scripts/fortran/parser.rb
@@ -32,10 +32,19 @@
 # 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
+# This file contains a parser which takes fortran file and parses out the
+# function definition.
+#
+# Needless to say, the parser is highly adapted to the BLAS and LAPACK
+# sources when it comes to extracting additional information from the
+# comments (for example, which variables are input/output), but the
+# extraction of the types should be rather generic.
+#
+# Main entry point is +parse_file+
+
+require 'fortran/types'
 
+module Fortran
   # Fortran 70 types
   # Source: http://www.nacs.uci.edu/dcslib/sun/compilers/fortran/f77rm/2_data.doc.html
   Types = ['BYTE',
@@ -44,39 +53,50 @@ module Fortran
            'CHARACTER\*\(\s*\*\s*\)',
            'COMPLEX(?:\*(?:8|16))?',
            'DOUBLE\ COMPLEX',
-           'DOUBLE\ PRECISION', 
+           '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
+  #
+  # Regular expressions used in the parser
+  #
+  # Stored here for better performance
+  #
 
-  # Return a Fortran function object.
-  def self.function(return_type, name, args)
-    Routine.new FortranType.new(return_type), name, args
-  end
+  # Matches e.g. SUBROUTINE DAXPY(N,DA,DX,INCX,DY, INCY)
+  SubroutineDecl =
+    Regexp.compile /\A\s+SUBROUTINE ([A-Z0-9]+)\(\ *([A-Z0-9, ]+)\ *\)/
+
+  # Matches e.g. DOUBLE PRECISION FUNCTION DDOT(N,DX,INCX,DY,INCY)
+  FunctionDecl =
+    Regexp.compile /\A\s+([A-Z ]+) FUNCTION ([A-Z0-9]+)\(\ *([A-Z0-9, ]+)\ *\)/
+
+  # Matches e.g. INTEGER INCX,INCY,N
+  VariableDecl =
+    Regexp.compile /\A\s+(#{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*]+\))?/
+
+  # Matches e.g. "*  LDA     - "
+  BLASArgumentCommentStart =
+    Regexp.compile /\A\*\s+([A-Z]+)\s+-\s/
+
+  UnchangedOnExit =
+    Regexp.compile /\A\*\s+Unchanged on exit./
 
-  # Concatenate all continuated lines. These are lines where there is a 
+  # Concatenate all continuated lines. These are lines where there is a
   # mark ('$' or 'C') in the 5th column. For example:
   #
   #  1234567890
@@ -89,185 +109,15 @@ module Fortran
     m = []
     lines.each do |l|
       l.chomp!
-      if l =~ /^     [$C]\ *( .+)/ then 
+      if l =~ /^     [$C]\ *( .+)/ then
         m[-1] << $1
-      else 
+      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.
   #
@@ -284,25 +134,28 @@ module Fortran
     routine = nil
     lines = f.readlines
     lines = Fortran.parse_continuations(lines)
+    blas_arg = nil
 
     lines.each do |l|
-      #puts l
+      #puts '[' + l.tr(' ','.') + ']'
       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 
+      when SubroutineDecl
         name = $1
         args = $2.scan /[A-Z0-9]+/
+        puts "--- " + name if $debug
         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
+        puts "   FunctionDecl matched" if $debug
         #
         # parse argument types, e.g.
         #
@@ -310,10 +163,10 @@ module Fortran
         #      COMPLEX*16       A( LDA, * ), VL( LDVL, * ), VR( L...
         #
       when VariableDecl
-          puts "#$1 -> #$2" if $debug
+        puts "#$1 -> #$2" if $debug
         type = $1
-        args = $2.scan ArgumentParens 
-        args.each do |argname| 
+        args = $2.scan ArgumentParens
+        args.each do |argname|
           puts "  #{argname} -> #{type}" if $debug
           if argname =~ /([A-Z0-9]+)\ *\(.*\)/
             argname = $1
@@ -325,14 +178,14 @@ module Fortran
             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}"
+        puts "#{args} -> comment \"#{comment}\"" if $debug
         args.split(',').each do |argname|
           at = routine.argtype[argname]
           if at
@@ -341,6 +194,23 @@ module Fortran
             puts "Warning: cannot add comment to variable #{argname} in file #{f.path} line \"#{l}\" (argument not defined)"
           end
         end
+        #
+        # Parser beginning argument comments for BLAS
+        #
+      when BLASArgumentCommentStart
+        blas_arg = $1
+        puts ">> #{l} << #{$1}" if $debug
+      when UnchangedOnExit
+        unless blas_arg.nil?
+          at = routine.argtype[blas_arg]
+          if at
+            puts "   adding (input)" if $debug
+            at.comment = 'input'
+          else
+            puts "Warning: cannot add input flag to variable #{blas_arg} in file #{f.path} line #{l} (argument not defined)"
+          end
+          blas_arg = nil
+        end
       end
     end
     return routine
diff --git a/scripts/fortran/types.rb b/scripts/fortran/types.rb
new file mode 100644
index 0000000..e3167f2
--- /dev/null
+++ b/scripts/fortran/types.rb
@@ -0,0 +1,192 @@
+## --- 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 file defines the main types for representing
+# functions/subroutines and their arguments.
+#
+# Two helper functions +subroutine+ and +function+ are defined which
+# construct a Routine object representing either a subroutine (with
+# return type 'VOID' or a function.
+#
+# Note that all types are basically represented by strings.
+#
+# Ideally, all the information about different types of arguments
+# should be contained in the classes FortranType or Routine, and
+# not encoded "by hand" elsewhere.
+module Fortran
+  # 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' }
+
+  # Map fortran types to a unique name (via DefaultTypes).
+  def self.standardize_type(name)
+    name.strip!
+    DefaultTypes.fetch name, name
+  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
+
+  # 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
+
+    def output?
+      comment.nil? or comment =~ /output/
+    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]}"
+      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
+
+    def output?(name)
+       @argtype[name].output?
+    end
+  end
+end
diff --git a/scripts/fortranwrapper.rb b/scripts/fortranwrapper.rb
index f616683..7ebf48f 100644
--- a/scripts/fortranwrapper.rb
+++ b/scripts/fortranwrapper.rb
@@ -44,9 +44,9 @@ $LOAD_PATH << $SCRIPT_DIR
 require 'erb'
 require 'optparse'
 
-require 'fortran'
+require 'fortran/types'
+require 'fortran/parser'
 require 'fortran/java'
-require 'fortran/c'
 
 Banner = <<EOS
 A wrapper of fortran functions for JNI
@@ -104,9 +104,13 @@ else
       routines << routine
     end
   end
+  File.open(FORTRANWRAPPER_DUMP, "w") {|f| Marshal.dump(routines, f)}
 end
 
-File.open(FORTRANWRAPPER_DUMP, "w") {|f| Marshal.dump(routines, f)}
+#routines.each do |r|
+#  puts r
+#end
+#exit
 
 #puts "Parsed #{number_of_routines} routines"
 def generate(template_file, package, klass, routines)
diff --git a/scripts/java-class.java b/scripts/java-class.java
index 7618390..003adf8 100644
--- a/scripts/java-class.java
+++ b/scripts/java-class.java
@@ -36,24 +36,59 @@
 
 package <%= package %>;
 
-import org.jblas.core.ComplexFloat;
-import org.jblas.core.ComplexDouble;
-
+/**
+ * Native BLAS and LAPACK functions.
+ *
+ * <p>The <%= classname %> class contains the native BLAS and LAPACK functions. Each
+ * Fortran function is mapped to a static method of this class. For each array argument,
+ * an additional parameter is introduced which gives the offset from the beginning of
+ * the passed array. In C, you would be able to pass a different pointer, but
+ * in Java, you can only pass the whole array.</p>
+ *
+ * <p>Note that due to the way the JNI is usually implemented, the arrays are first
+ * copied outside of the JVM before the function is called. This means that
+ * functions whose runtime is linear in the amount of memory do usually not
+ * run faster just because you are using a native implementation. This holds true
+ * for most Level 1 BLAS routines (like vector addition), and unfortunately also
+ * for most Level 2 BLAS routines (like matrix-vector multiplication). For these,
+ * there exists a class JavaBlas which contains Java implementations.</p>
+ *
+ * <p>In LAPACK, there exist routines which require workspace to be allocated together
+ * with a standard procedure for computing the size of these workspaces. jblas
+ * automatically also generates wrappers for these routines with automatic
+ * workspace allocation. These routines have the same name, but the workspace
+ * arguments are removed.</p>
+ *
+ * <p>Finally, an example: The fortran routine<pre>
+ * SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY)
+ *     DOUBLE PRECISION DA
+ *     INTEGER INCX,INCY,N
+ *     DOUBLE PRECISION DX(*),DY(*)
+ * </pre>
+ * becomes <pre>
+ * public static native void daxpy(int n, double da, double[] dx, int dxIdx,
+ *    int incx, double[] dy, int dyIdx, int incy);
+ * </pre>
+ */
 public class <%= classname %> {
 
   static {
 	  try {
-		  System.loadLibrary("j<%= classname.downcase %>");
+		  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("j<%= classname.downcase %>");
+		  new org.jblas.util.LibraryLoader().loadLibrary("jblas");
 	  }
   } 
 
+  private static int[] intDummy = new int[1];
+  private static double[] doubleDummy = new double[1];
+  private static float[] floatDummy = new float[1];
+
 <% for r in routines -%>
 <%= generate_native_declaration r %>
 <% end %>
diff --git a/scripts/java-impl.c b/scripts/java-impl.c
index 071f21c..76c0356 100644
--- a/scripts/java-impl.c
+++ b/scripts/java-impl.c
@@ -34,7 +34,7 @@
 
 #include "<%= header_file_name %>.h"
 
-#define CORE_PACKAGE "org/jblas/core/"
+#define CORE_PACKAGE "org/jblas/"
 
 /*
  * For convenience, we define some typedefs here which have the
diff --git a/scripts/render-textile.rb b/scripts/render-textile.rb
index 128e766..5c63e60 100644
--- a/scripts/render-textile.rb
+++ b/scripts/render-textile.rb
@@ -1,3 +1,37 @@
+## --- 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'
 
 require 'rubygems'
diff --git a/scripts/static_class_to_float.rb b/scripts/static_class_to_float.rb
index 7aa9d9a..d5eebd0 100644
--- a/scripts/static_class_to_float.rb
+++ b/scripts/static_class_to_float.rb
@@ -71,11 +71,11 @@ def translate(cl, s)
   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! /NativeBlas\.dz/, 'NativeBlas.sc'
+  copybody.gsub! /NativeBlas\.d/, 'NativeBlas.s'
+  copybody.gsub! /NativeBlas\.z/, 'NativeBlas.c'
+  copybody.gsub! /NativeBlas\.idamax/, 'NativeBlas.isamax'
+  copybody.gsub! /NativeBlas\.izamax/, 'NativeBlas.icamax'
   copybody.gsub!(/([a-z]+)Double/, '\1Float')
 
   # construct output file
diff --git a/config/path.rb b/scripts/template_context.rb
similarity index 65%
copy from config/path.rb
copy to scripts/template_context.rb
index 85b0b3f..c610f4f 100644
--- a/config/path.rb
+++ b/scripts/template_context.rb
@@ -32,24 +32,28 @@
 # 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
+# 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
-  return
 end
diff --git a/scripts/test_fortranwrapper b/scripts/test_fortranwrapper
old mode 100644
new mode 100755
diff --git a/src/org/jblas/core/ComplexDouble.java b/src/org/jblas/ComplexDouble.java
similarity index 99%
rename from src/org/jblas/core/ComplexDouble.java
rename to src/org/jblas/ComplexDouble.java
index b8e6e73..2f0664f 100644
--- a/src/org/jblas/core/ComplexDouble.java
+++ b/src/org/jblas/ComplexDouble.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.core;
+package org.jblas;
 
 import static java.lang.Math.sqrt;
 
diff --git a/src/org/jblas/la/ComplexDoubleMatrix.java b/src/org/jblas/ComplexDoubleMatrix.java
similarity index 94%
rename from src/org/jblas/la/ComplexDoubleMatrix.java
rename to src/org/jblas/ComplexDoubleMatrix.java
index f44a292..7d617ec 100644
--- a/src/org/jblas/la/ComplexDoubleMatrix.java
+++ b/src/org/jblas/ComplexDoubleMatrix.java
@@ -34,1552 +34,1551 @@
  */
 // --- 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', '^'))
+package org.jblas;
+
+import org.jblas.exceptions.SizeException;
+
+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);
+            
+            NativeBlas.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)
+                NativeBlas.dcopy(length, real.data, 0, 1, data, 0, 2);
+            if (imag != null)
+                NativeBlas.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);
+		NativeBlas.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++) {
+			NativeBlas.zcopy(A.rows, A.data, A.index(0, i), 1, result.data, result.index(0, i), 1);
+			NativeBlas.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) {
+		NativeBlas.zswap(rows, data, index(0, i), 1, data, index(0, j), 1);
+		return this;
+	}
+	
+	public ComplexDoubleMatrix swapRows(int i, int j) {
+		NativeBlas.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);
+		
+		NativeBlas.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);
+		NativeBlas.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);
+            NativeBlas.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);
+            NativeBlas.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);
+		NativeBlas.zcopy(rows, data, index(0, c), 1, result.data, 0, 1);
+		return result;
+	}
+	
+	public void putColumn(int c, ComplexDoubleMatrix v) {
+		NativeBlas.zcopy(rows, v.data, 0, 1, data, index(0, c), 1);
+	}
+
+	public ComplexDoubleMatrix getRow(int r) {
+		ComplexDoubleMatrix result = new ComplexDoubleMatrix(1, columns);
+		NativeBlas.zcopy(columns, data, index(r, 0), rows, result.data, 0, 1);
+		return result;
+	}
+	
+	public void putRow(int r, ComplexDoubleMatrix v) {
+		NativeBlas.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++) {
+			NativeBlas.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++) {
+			NativeBlas.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++) {
+			NativeBlas.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++) {
+			NativeBlas.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) {
@@ -2008,4 +2007,4 @@ public class ComplexDoubleMatrix {
 	   return xori(new ComplexDouble(value));
 	 }
 //RJPP-END--------------------------------------------------------------
-}
+}
diff --git a/src/org/jblas/core/ComplexFloat.java b/src/org/jblas/ComplexFloat.java
similarity index 99%
rename from src/org/jblas/core/ComplexFloat.java
rename to src/org/jblas/ComplexFloat.java
index de1c885..a44301a 100644
--- a/src/org/jblas/core/ComplexFloat.java
+++ b/src/org/jblas/ComplexFloat.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.core;
+package org.jblas;
 
 import static java.lang.Math.sqrt;
 
diff --git a/src/org/jblas/la/ComplexFloatMatrix.java b/src/org/jblas/ComplexFloatMatrix.java
similarity index 94%
rename from src/org/jblas/la/ComplexFloatMatrix.java
rename to src/org/jblas/ComplexFloatMatrix.java
index 1750df0..0f2e6e6 100644
--- a/src/org/jblas/la/ComplexFloatMatrix.java
+++ b/src/org/jblas/ComplexFloatMatrix.java
@@ -34,1552 +34,1551 @@
  */
 // --- 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', '^'))
+package org.jblas;
+
+import org.jblas.exceptions.SizeException;
+
+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);
+            
+            NativeBlas.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)
+                NativeBlas.scopy(length, real.data, 0, 1, data, 0, 2);
+            if (imag != null)
+                NativeBlas.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);
+		NativeBlas.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++) {
+			NativeBlas.ccopy(A.rows, A.data, A.index(0, i), 1, result.data, result.index(0, i), 1);
+			NativeBlas.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) {
+		NativeBlas.cswap(rows, data, index(0, i), 1, data, index(0, j), 1);
+		return this;
+	}
+	
+	public ComplexFloatMatrix swapRows(int i, int j) {
+		NativeBlas.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);
+		
+		NativeBlas.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);
+		NativeBlas.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);
+            NativeBlas.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);
+            NativeBlas.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);
+		NativeBlas.ccopy(rows, data, index(0, c), 1, result.data, 0, 1);
+		return result;
+	}
+	
+	public void putColumn(int c, ComplexFloatMatrix v) {
+		NativeBlas.ccopy(rows, v.data, 0, 1, data, index(0, c), 1);
+	}
+
+	public ComplexFloatMatrix getRow(int r) {
+		ComplexFloatMatrix result = new ComplexFloatMatrix(1, columns);
+		NativeBlas.ccopy(columns, data, index(r, 0), rows, result.data, 0, 1);
+		return result;
+	}
+	
+	public void putRow(int r, ComplexFloatMatrix v) {
+		NativeBlas.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++) {
+			NativeBlas.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++) {
+			NativeBlas.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++) {
+			NativeBlas.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++) {
+			NativeBlas.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) {
@@ -2008,4 +2007,4 @@ public class ComplexFloatMatrix {
 	   return xori(new ComplexFloat(value));
 	 }
 //RJPP-END--------------------------------------------------------------
-}
+}
diff --git a/src/org/jblas/ConvertsToDoubleMatrix.java b/src/org/jblas/ConvertsToDoubleMatrix.java
new file mode 100644
index 0000000..890fbd2
--- /dev/null
+++ b/src/org/jblas/ConvertsToDoubleMatrix.java
@@ -0,0 +1,14 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas;
+
+/**
+ *
+ * @author mikio
+ */
+public interface ConvertsToDoubleMatrix {
+    public DoubleMatrix convertToDoubleMatrix();
+}
diff --git a/src/org/jblas/ConvertsToFloatMatrix.java b/src/org/jblas/ConvertsToFloatMatrix.java
new file mode 100644
index 0000000..f3c6c78
--- /dev/null
+++ b/src/org/jblas/ConvertsToFloatMatrix.java
@@ -0,0 +1,14 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas;
+
+/**
+ *
+ * @author mikio
+ */
+public interface ConvertsToFloatMatrix {
+    public FloatMatrix convertToFloatMatrix();
+}
diff --git a/src/org/jblas/Decompose.java b/src/org/jblas/Decompose.java
new file mode 100644
index 0000000..655fcaf
--- /dev/null
+++ b/src/org/jblas/Decompose.java
@@ -0,0 +1,82 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.jblas;
+
+import org.jblas.exceptions.LapackArgumentException;
+import org.jblas.exceptions.LapackPositivityException;
+import org.jblas.util.Permutations;
+import static org.jblas.util.Functions.min;
+
+/**
+ * Matrix which collects all kinds of decompositions.
+ */
+public class Decompose {
+
+    public static class LUDecomposition<T> {
+
+        public T l;
+        public T u;
+        public T p;
+
+        public LUDecomposition(T l, T u, T p) {
+            this.l = l;
+            this.u = u;
+            this.p = p;
+        }
+    }
+
+    public static LUDecomposition<DoubleMatrix> lu(DoubleMatrix A) {
+        int[] ipiv = new int[min(A.rows, A.columns)];
+        DoubleMatrix result = A.dup();
+        NativeBlas.dgetrf(A.rows, A.columns, result.data, 0, A.rows, ipiv, 0);
+
+        // collect result
+        DoubleMatrix l = new DoubleMatrix(A.rows, min(A.rows, A.columns));
+        DoubleMatrix u = new DoubleMatrix(min(A.columns, A.rows), A.columns);
+        decomposeLowerUpper(result, l, u);
+        DoubleMatrix p = Permutations.permutationMatrixFromPivotIndices(A.rows, ipiv);
+        return new LUDecomposition<DoubleMatrix>(l, u, p);
+    }
+
+    private static void decomposeLowerUpper(DoubleMatrix A, DoubleMatrix L, DoubleMatrix U) {
+        for (int i = 0; i < A.rows; i++) {
+            for (int j = 0; j < A.columns; j++) {
+                if (i < j) {
+                    U.put(i, j, A.get(i, j));
+                } else if (i == j) {
+                    U.put(i, i, A.get(i, i));
+                    L.put(i, i, 1.0);
+                } else {
+                    L.put(i, j, A.get(i, j));
+                }
+
+            }
+        }
+    }
+
+    /**
+     * Compute Cholesky decomposition of A
+     *
+     * @param A symmetric, positive definite matrix (only upper half is used)
+     * @return upper triangular matrix U such that  A = U' * U
+     */
+    public static DoubleMatrix cholesky(DoubleMatrix A) {
+        DoubleMatrix result = A.dup();
+        int info = NativeBlas.dpotrf('U', A.rows, result.data, 0, A.rows);
+        if (info < 0) {
+            throw new LapackArgumentException("DPOTRF", -info);
+        } else if (info > 0) {
+            throw new LapackPositivityException("DPOTRF", "Minor " + info + " was negative. Matrix must be positive definite.");
+        }
+        clearLower(result);
+        return result;
+    }
+
+    private static void clearLower(DoubleMatrix A) {
+        for (int j = 0; j < A.columns; j++)
+            for (int i = j + 1; i < A.rows; i++)
+                A.put(i, j, 0.0);
+    }
+}
diff --git a/src/org/jblas/la/DoubleFunction.java b/src/org/jblas/DoubleFunction.java
similarity index 98%
rename from src/org/jblas/la/DoubleFunction.java
rename to src/org/jblas/DoubleFunction.java
index fc6d54e..35662c3 100644
--- a/src/org/jblas/la/DoubleFunction.java
+++ b/src/org/jblas/DoubleFunction.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 /**
  * Represents a function on doubles.
diff --git a/src/org/jblas/la/DoubleMatrix.java b/src/org/jblas/DoubleMatrix.java
similarity index 91%
rename from src/org/jblas/la/DoubleMatrix.java
rename to src/org/jblas/DoubleMatrix.java
index 33b1b48..4c229e5 100644
--- a/src/org/jblas/la/DoubleMatrix.java
+++ b/src/org/jblas/DoubleMatrix.java
@@ -2,6 +2,7 @@
 /* 
  * Copyright (c) 2009, Mikio L. Braun
  * Copyright (c) 2008, Johannes Schaback
+ * Copyright (c) 2009, Jan Saputra Müller
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -35,23 +36,26 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.exceptions.SizeException;
-import org.jblas.la.ranges.Range;
+import org.jblas.exceptions.SizeException;
+import org.jblas.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.AbstractList;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * A general matrix class for <tt>double</tt> typed values.
@@ -1016,7 +1020,7 @@ public class DoubleMatrix {
             resize(a.rows, a.columns);
         }
 
-        System.arraycopy(data, 0, a.data, 0, length);
+        System.arraycopy(a.data, 0, data, 0, length);
         return a;
     }
 
@@ -1034,13 +1038,13 @@ public class DoubleMatrix {
 
     /** 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);
+        NativeBlas.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);
+        NativeBlas.dswap(columns, data, index(i, 0), rows, data, index(j, 0), rows);
         return this;
     }
 
@@ -1285,6 +1289,88 @@ public class DoubleMatrix {
         return result;
     }
 
+    /**
+     * A wrapper which allows to view a matrix as a List of Doubles (read-only!).
+     * Also implements the {@link ConvertsToDoubleMatrix} interface.
+     */
+    public class ElementsAsListView extends AbstractList<Double> implements ConvertsToDoubleMatrix {
+        private DoubleMatrix me;
+
+        public ElementsAsListView(DoubleMatrix me) {
+            this.me = me;
+        }
+
+        @Override
+        public Double get(int index) {
+            return me.get(index);
+        }
+
+        @Override
+        public int size() {
+            return me.length;
+        }
+
+        public DoubleMatrix convertToDoubleMatrix() {
+            return me;
+        }
+    }
+
+    public class RowsAsListView extends AbstractList<DoubleMatrix> implements ConvertsToDoubleMatrix {
+        private DoubleMatrix me;
+
+        public RowsAsListView(DoubleMatrix me) {
+            this.me = me;
+        }
+
+        @Override
+        public DoubleMatrix get(int index) {
+            return getRow(index);
+        }
+
+        @Override
+        public int size() {
+            return rows;
+        }
+
+        public DoubleMatrix convertToDoubleMatrix() {
+            return me;
+        }
+    }
+
+    public class ColumnsAsListView extends AbstractList<DoubleMatrix> implements ConvertsToDoubleMatrix {
+        private DoubleMatrix me;
+
+        public ColumnsAsListView(DoubleMatrix me) {
+            this.me = me;
+        }
+
+        @Override
+        public DoubleMatrix get(int index) {
+            return getColumn(index);
+        }
+
+        @Override
+        public int size() {
+            return columns;
+        }
+
+        public DoubleMatrix convertToDoubleMatrix() {
+            return me;
+        }
+    }
+
+    public List<Double> elementsAsList() {
+        return new ElementsAsListView(this);
+    }
+
+    public List<DoubleMatrix> rowsAsList() {
+        return new RowsAsListView(this);
+    }
+
+    public List<DoubleMatrix> columnsAsList() {
+        return new ColumnsAsListView(this);
+    }
+
     /**************************************************************************
      * Arithmetic Operations
      */
@@ -1547,7 +1633,67 @@ public class DoubleMatrix {
     public DoubleMatrix truth() {
         return dup().truthi();
     }
-
+ 
+    /**
+    * Calculate matrix exponential of a square matrix.
+    * 
+    * A scaled Pade approximation algorithm is used.
+    * The algorithm has been directly translated from Golub & Van Loan "Matrix Computations",
+    * algorithm 11.3.1. Special Horner techniques from 11.2 are also used to minimize the number
+    * of matrix multiplications. 
+    * 
+    * @param A square matrix
+    * @return matrix exponential of A
+    */
+    public static DoubleMatrix expm(DoubleMatrix A)
+    {
+		// constants for pade approximation
+		final double c0 = 1.0;
+		final double c1 = 0.5;
+		final double c2 = 0.12;
+		final double c3 = 0.01833333333333333;
+		final double c4 = 0.0019927536231884053;
+		final double c5 = 1.630434782608695E-4;
+		final double c6 = 1.0351966873706E-5;
+		final double c7 = 5.175983436853E-7;
+		final double c8 = 2.0431513566525E-8;
+		final double c9 = 6.306022705717593E-10;
+		final double c10 = 1.4837700484041396E-11;
+		final double c11 = 2.5291534915979653E-13;
+		final double c12 = 2.8101705462199615E-15;
+		final double c13 = 1.5440497506703084E-17;
+		
+		int j = Math.max(0, 1 + (int)Math.floor(Math.log(A.normmax())/Math.log(2)));
+		DoubleMatrix As = A.div((double)Math.pow(2, j)); // scaled version of A
+		int n = A.getRows();
+		
+		// calculate D and N using special Horner techniques
+		DoubleMatrix As_2 = As.mmul(As);
+		DoubleMatrix As_4 = As_2.mmul(As_2);
+		DoubleMatrix As_6 = As_4.mmul(As_2);
+		// U = c0*I + c2*A^2 + c4*A^4 + (c6*I + c8*A^2 + c10*A^4 + c12*A^6)*A^6
+		DoubleMatrix U = DoubleMatrix.eye(n).muli(c0).addi(As_2.mul(c2)).addi(As_4.mul(c4)).addi(
+				DoubleMatrix.eye(n).muli(c6).addi(As_2.mul(c8)).addi(As_4.mul(c10)).addi(As_6.mul(c12)).mmuli(As_6));
+		// V = c1*I + c3*A^2 + c5*A^4 + (c7*I + c9*A^2 + c11*A^4 + c13*A^6)*A^6
+		DoubleMatrix V = DoubleMatrix.eye(n).muli(c1).addi(As_2.mul(c3)).addi(As_4.mul(c5)).addi(
+				DoubleMatrix.eye(n).muli(c7).addi(As_2.mul(c9)).addi(As_4.mul(c11)).addi(As_6.mul(c13)).mmuli(As_6));
+		
+		DoubleMatrix AV = As.mmuli(V);
+		DoubleMatrix N = U.add(AV);
+		DoubleMatrix D = U.subi(AV);
+		
+		// solve DF = N for F
+		DoubleMatrix F = Solve.solve(D, N);
+		
+		// now square j times
+		for(int k = 0; k < j; k++)
+		{
+			F.mmuli(F);
+		}
+		
+		return F;
+    }
+    
     /****************************************************************
      * Rank one-updates
      */
@@ -1794,6 +1940,15 @@ public class DoubleMatrix {
         }
         return s;
     }
+    
+    /** Computes the product of all elements of the matrix */
+    public double prod() {
+        double p = 1.0;
+        for (int i = 0; i < length; i++) {
+            p *= get(i);
+        }
+        return p;
+    }
 
     /**
      * Computes the mean value of all elements in the matrix,
@@ -1829,27 +1984,57 @@ public class DoubleMatrix {
         return SimpleBlas.dot(this, other);
     }
 
+    /** 
+     * Computes the projection coefficient of other on this.
+     *
+     * The returned scalar times <tt>this</tt> is the orthogonal projection
+     * of <tt>other</tt> on <tt>this</tt>.
+     */
+    public double project(DoubleMatrix other) {
+        other.checkLength(length);
+        double norm = 0, dot = 0;
+        for (int i = 0; i < this.length; i++) {
+            double x = get(i);
+            norm += x*x;
+            dot += x*other.get(i);
+        }
+        return dot/norm;
+    }
+
     /**
      * The Euclidean norm of the matrix as vector, also the Frobenius
      * norm of the matrix.
      */
     public double norm2() {
-        return SimpleBlas.nrm2(this);
+        double norm = 0.0;
+        for (int i = 0; i < length; i++) {
+            norm += get(i) * get(i);
+        }
+        return (double)Math.sqrt(norm);
     }
 
     /**
      * 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));
+        double max = 0.0;
+        for (int i = 0; i < length; i++) {
+            double a = Math.abs(get(i));
+            if (a > max)
+                max = a;
+        }
+        return max;
     }
 
     /**
      * The 1-norm of the matrix as vector (sum of absolute values of elements).
      */
     public double norm1() {
-        return SimpleBlas.asum(this);
+        double norm = 0.0;
+        for (int i = 0; i < length; i++) {
+            norm += Math.abs(get(i));
+        }
+        return norm;
     }
 
     /**
@@ -2119,9 +2304,9 @@ public class DoubleMatrix {
     /** 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);
-        }
+        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;
     }
 
@@ -2133,9 +2318,9 @@ public class DoubleMatrix {
     /** 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);
-        }
+        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;
     }
 
@@ -2148,9 +2333,9 @@ public class DoubleMatrix {
     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);
-        }
+        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;
     }
 
@@ -2162,9 +2347,9 @@ public class DoubleMatrix {
     /** 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);
-        }
+        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;
     }
 
@@ -2175,13 +2360,13 @@ public class DoubleMatrix {
 
     /** Multiply a row by a scalar. */
     public DoubleMatrix mulRow(int r, double scale) {
-        Blas.dscal(columns, scale, data, index(r, 0), rows);
+        NativeBlas.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);
+        NativeBlas.dscal(rows, scale, data, index(0, c), 1);
         return this;
     }
 
@@ -2214,6 +2399,30 @@ public class DoubleMatrix {
         return dup().muliRowVector(x);
     }
 
+    public DoubleMatrix diviRowVector(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;
+    }
+
+    public DoubleMatrix divRowVector(DoubleMatrix x) {
+        return dup().diviRowVector(x);
+    }
+
+    public DoubleMatrix diviColumnVector(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;
+    }
+
+    public DoubleMatrix divColumnVector(DoubleMatrix x) {
+        return dup().diviColumnVector(x);
+    }
+
     /**
      * Writes out this matrix to the given data stream.
      * @param dos the data output stream to write to.
@@ -2318,6 +2527,49 @@ public class DoubleMatrix {
         return result;
     }
 
+    public static DoubleMatrix loadCSVFile(String filename) throws IOException {
+        BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+
+        List<DoubleMatrix> rows = new LinkedList<DoubleMatrix>();
+        String line;
+        int columns = -1;
+        while ((line = is.readLine()) != null) {
+            String[] elements = line.split(",");
+            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 + ".");
+                }
+            }
+
+            DoubleMatrix row = new DoubleMatrix(columns);
+            for (int c = 0; c < columns; c++)
+                row.put(c, Double.valueOf(elements[c]));
+            rows.add(row);
+        }
+        is.close();
+
+        System.out.println("Done reading file");
+
+        DoubleMatrix result = new DoubleMatrix(rows.size(), columns);
+        int r = 0;
+        Iterator<DoubleMatrix> ri = rows.iterator();
+        while (ri.hasNext()) {
+            result.putRow(r, ri.next());
+            r++;
+        }
+        return result;
+    }
+
     /****************************************************************
      * Autogenerated code
      */
diff --git a/src/org/jblas/la/Eigen.java b/src/org/jblas/Eigen.java
similarity index 99%
rename from src/org/jblas/la/Eigen.java
rename to src/org/jblas/Eigen.java
index fe3b6df..8a40d7c 100644
--- a/src/org/jblas/la/Eigen.java
+++ b/src/org/jblas/Eigen.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 /**
  * <p>Eigenvalue and Eigenvector related functions.</p>
diff --git a/src/org/jblas/la/FloatFunction.java b/src/org/jblas/FloatFunction.java
similarity index 98%
copy from src/org/jblas/la/FloatFunction.java
copy to src/org/jblas/FloatFunction.java
index 150e58c..23cc618 100644
--- a/src/org/jblas/la/FloatFunction.java
+++ b/src/org/jblas/FloatFunction.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 /**
  * Represents a function on floats.
diff --git a/src/org/jblas/la/FloatMatrix.java b/src/org/jblas/FloatMatrix.java
similarity index 91%
rename from src/org/jblas/la/FloatMatrix.java
rename to src/org/jblas/FloatMatrix.java
index 2bda548..44af945 100644
--- a/src/org/jblas/la/FloatMatrix.java
+++ b/src/org/jblas/FloatMatrix.java
@@ -2,6 +2,7 @@
 /* 
  * Copyright (c) 2009, Mikio L. Braun
  * Copyright (c) 2008, Johannes Schaback
+ * Copyright (c) 2009, Jan Saputra Müller
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -35,23 +36,26 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.exceptions.SizeException;
-import org.jblas.la.ranges.Range;
+import org.jblas.exceptions.SizeException;
+import org.jblas.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.AbstractList;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * A general matrix class for <tt>float</tt> typed values.
@@ -1016,7 +1020,7 @@ public class FloatMatrix {
             resize(a.rows, a.columns);
         }
 
-        System.arraycopy(data, 0, a.data, 0, length);
+        System.arraycopy(a.data, 0, data, 0, length);
         return a;
     }
 
@@ -1034,13 +1038,13 @@ public class FloatMatrix {
 
     /** 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);
+        NativeBlas.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);
+        NativeBlas.sswap(columns, data, index(i, 0), rows, data, index(j, 0), rows);
         return this;
     }
 
@@ -1285,6 +1289,88 @@ public class FloatMatrix {
         return result;
     }
 
+    /**
+     * A wrapper which allows to view a matrix as a List of Doubles (read-only!).
+     * Also implements the {@link ConvertsToFloatMatrix} interface.
+     */
+    public class ElementsAsListView extends AbstractList<Float> implements ConvertsToFloatMatrix {
+        private FloatMatrix me;
+
+        public ElementsAsListView(FloatMatrix me) {
+            this.me = me;
+        }
+
+        @Override
+        public Float get(int index) {
+            return me.get(index);
+        }
+
+        @Override
+        public int size() {
+            return me.length;
+        }
+
+        public FloatMatrix convertToFloatMatrix() {
+            return me;
+        }
+    }
+
+    public class RowsAsListView extends AbstractList<FloatMatrix> implements ConvertsToFloatMatrix {
+        private FloatMatrix me;
+
+        public RowsAsListView(FloatMatrix me) {
+            this.me = me;
+        }
+
+        @Override
+        public FloatMatrix get(int index) {
+            return getRow(index);
+        }
+
+        @Override
+        public int size() {
+            return rows;
+        }
+
+        public FloatMatrix convertToFloatMatrix() {
+            return me;
+        }
+    }
+
+    public class ColumnsAsListView extends AbstractList<FloatMatrix> implements ConvertsToFloatMatrix {
+        private FloatMatrix me;
+
+        public ColumnsAsListView(FloatMatrix me) {
+            this.me = me;
+        }
+
+        @Override
+        public FloatMatrix get(int index) {
+            return getColumn(index);
+        }
+
+        @Override
+        public int size() {
+            return columns;
+        }
+
+        public FloatMatrix convertToFloatMatrix() {
+            return me;
+        }
+    }
+
+    public List<Float> elementsAsList() {
+        return new ElementsAsListView(this);
+    }
+
+    public List<FloatMatrix> rowsAsList() {
+        return new RowsAsListView(this);
+    }
+
+    public List<FloatMatrix> columnsAsList() {
+        return new ColumnsAsListView(this);
+    }
+
     /**************************************************************************
      * Arithmetic Operations
      */
@@ -1547,7 +1633,67 @@ public class FloatMatrix {
     public FloatMatrix truth() {
         return dup().truthi();
     }
-
+ 
+    /**
+    * Calculate matrix exponential of a square matrix.
+    * 
+    * A scaled Pade approximation algorithm is used.
+    * The algorithm has been directly translated from Golub & Van Loan "Matrix Computations",
+    * algorithm 11.3f.1. Special Horner techniques from 11.2f are also used to minimize the number
+    * of matrix multiplications. 
+    * 
+    * @param A square matrix
+    * @return matrix exponential of A
+    */
+    public static FloatMatrix expm(FloatMatrix A)
+    {
+		// constants for pade approximation
+		final float c0 = 1.0f;
+		final float c1 = 0.5f;
+		final float c2 = 0.12f;
+		final float c3 = 0.01833333333333333f;
+		final float c4 = 0.0019927536231884053f;
+		final float c5 = 1.630434782608695E-4f;
+		final float c6 = 1.0351966873706E-5f;
+		final float c7 = 5.175983436853E-7f;
+		final float c8 = 2.0431513566525E-8f;
+		final float c9 = 6.306022705717593E-10f;
+		final float c10 = 1.4837700484041396E-11f;
+		final float c11 = 2.5291534915979653E-13f;
+		final float c12 = 2.8101705462199615E-15f;
+		final float c13 = 1.5440497506703084E-17f;
+		
+		int j = Math.max(0, 1 + (int)Math.floor(Math.log(A.normmax())/Math.log(2)));
+		FloatMatrix As = A.div((float)Math.pow(2, j)); // scaled version of A
+		int n = A.getRows();
+		
+		// calculate D and N using special Horner techniques
+		FloatMatrix As_2 = As.mmul(As);
+		FloatMatrix As_4 = As_2.mmul(As_2);
+		FloatMatrix As_6 = As_4.mmul(As_2);
+		// U = c0*I + c2*A^2 + c4*A^4 + (c6*I + c8*A^2 + c10*A^4 + c12*A^6)*A^6
+		FloatMatrix U = FloatMatrix.eye(n).muli(c0).addi(As_2.mul(c2)).addi(As_4.mul(c4)).addi(
+				FloatMatrix.eye(n).muli(c6).addi(As_2.mul(c8)).addi(As_4.mul(c10)).addi(As_6.mul(c12)).mmuli(As_6));
+		// V = c1*I + c3*A^2 + c5*A^4 + (c7*I + c9*A^2 + c11*A^4 + c13*A^6)*A^6
+		FloatMatrix V = FloatMatrix.eye(n).muli(c1).addi(As_2.mul(c3)).addi(As_4.mul(c5)).addi(
+				FloatMatrix.eye(n).muli(c7).addi(As_2.mul(c9)).addi(As_4.mul(c11)).addi(As_6.mul(c13)).mmuli(As_6));
+		
+		FloatMatrix AV = As.mmuli(V);
+		FloatMatrix N = U.add(AV);
+		FloatMatrix D = U.subi(AV);
+		
+		// solve DF = N for F
+		FloatMatrix F = Solve.solve(D, N);
+		
+		// now square j times
+		for(int k = 0; k < j; k++)
+		{
+			F.mmuli(F);
+		}
+		
+		return F;
+    }
+    
     /****************************************************************
      * Rank one-updates
      */
@@ -1794,6 +1940,15 @@ public class FloatMatrix {
         }
         return s;
     }
+    
+    /** Computes the product of all elements of the matrix */
+    public float prod() {
+        float p = 1.0f;
+        for (int i = 0; i < length; i++) {
+            p *= get(i);
+        }
+        return p;
+    }
 
     /**
      * Computes the mean value of all elements in the matrix,
@@ -1829,27 +1984,57 @@ public class FloatMatrix {
         return SimpleBlas.dot(this, other);
     }
 
+    /** 
+     * Computes the projection coefficient of other on this.
+     *
+     * The returned scalar times <tt>this</tt> is the orthogonal projection
+     * of <tt>other</tt> on <tt>this</tt>.
+     */
+    public float project(FloatMatrix other) {
+        other.checkLength(length);
+        float norm = 0, dot = 0;
+        for (int i = 0; i < this.length; i++) {
+            float x = get(i);
+            norm += x*x;
+            dot += x*other.get(i);
+        }
+        return dot/norm;
+    }
+
     /**
      * The Euclidean norm of the matrix as vector, also the Frobenius
      * norm of the matrix.
      */
     public float norm2() {
-        return SimpleBlas.nrm2(this);
+        float norm = 0.0f;
+        for (int i = 0; i < length; i++) {
+            norm += get(i) * get(i);
+        }
+        return (float)Math.sqrt(norm);
     }
 
     /**
      * 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));
+        float max = 0.0f;
+        for (int i = 0; i < length; i++) {
+            float a = Math.abs(get(i));
+            if (a > max)
+                max = a;
+        }
+        return max;
     }
 
     /**
      * The 1-norm of the matrix as vector (sum of absolute values of elements).
      */
     public float norm1() {
-        return SimpleBlas.asum(this);
+        float norm = 0.0f;
+        for (int i = 0; i < length; i++) {
+            norm += Math.abs(get(i));
+        }
+        return norm;
     }
 
     /**
@@ -2119,9 +2304,9 @@ public class FloatMatrix {
     /** 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);
-        }
+        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;
     }
 
@@ -2133,9 +2318,9 @@ public class FloatMatrix {
     /** 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);
-        }
+        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;
     }
 
@@ -2148,9 +2333,9 @@ public class FloatMatrix {
     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);
-        }
+        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;
     }
 
@@ -2162,9 +2347,9 @@ public class FloatMatrix {
     /** 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);
-        }
+        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;
     }
 
@@ -2175,13 +2360,13 @@ public class FloatMatrix {
 
     /** Multiply a row by a scalar. */
     public FloatMatrix mulRow(int r, float scale) {
-        Blas.sscal(columns, scale, data, index(r, 0), rows);
+        NativeBlas.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);
+        NativeBlas.sscal(rows, scale, data, index(0, c), 1);
         return this;
     }
 
@@ -2214,6 +2399,30 @@ public class FloatMatrix {
         return dup().muliRowVector(x);
     }
 
+    public FloatMatrix diviRowVector(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;
+    }
+
+    public FloatMatrix divRowVector(FloatMatrix x) {
+        return dup().diviRowVector(x);
+    }
+
+    public FloatMatrix diviColumnVector(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;
+    }
+
+    public FloatMatrix divColumnVector(FloatMatrix x) {
+        return dup().diviColumnVector(x);
+    }
+
     /**
      * Writes out this matrix to the given data stream.
      * @param dos the data output stream to write to.
@@ -2318,6 +2527,49 @@ public class FloatMatrix {
         return result;
     }
 
+    public static FloatMatrix loadCSVFile(String filename) throws IOException {
+        BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
+
+        List<FloatMatrix> rows = new LinkedList<FloatMatrix>();
+        String line;
+        int columns = -1;
+        while ((line = is.readLine()) != null) {
+            String[] elements = line.split(",");
+            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 + ".");
+                }
+            }
+
+            FloatMatrix row = new FloatMatrix(columns);
+            for (int c = 0; c < columns; c++)
+                row.put(c, Float.valueOf(elements[c]));
+            rows.add(row);
+        }
+        is.close();
+
+        System.out.println("Done reading file");
+
+        FloatMatrix result = new FloatMatrix(rows.size(), columns);
+        int r = 0;
+        Iterator<FloatMatrix> ri = rows.iterator();
+        while (ri.hasNext()) {
+            result.putRow(r, ri.next());
+            r++;
+        }
+        return result;
+    }
+
     /****************************************************************
      * Autogenerated code
      */
diff --git a/src/org/jblas/la/Geometry.java b/src/org/jblas/Geometry.java
similarity index 99%
rename from src/org/jblas/la/Geometry.java
rename to src/org/jblas/Geometry.java
index 89186df..ed68408 100644
--- a/src/org/jblas/la/Geometry.java
+++ b/src/org/jblas/Geometry.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 /**
  * <p>General functions which are geometric in nature.</p>
diff --git a/src/org/jblas/la/JavaBlas.java b/src/org/jblas/JavaBlas.java
similarity index 99%
rename from src/org/jblas/la/JavaBlas.java
rename to src/org/jblas/JavaBlas.java
index f6184d8..e240799 100644
--- a/src/org/jblas/la/JavaBlas.java
+++ b/src/org/jblas/JavaBlas.java
@@ -38,9 +38,9 @@
  * To change this template, choose Tools | Templates
  * and open the template in the editor.
  */
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.exceptions.LapackException;
+import org.jblas.exceptions.LapackException;
 
 /**
  * <p>Implementation of some Blas functions, mostly those which require linear runtime
diff --git a/src/org/jblas/la/MatrixFunctions.java b/src/org/jblas/MatrixFunctions.java
similarity index 98%
rename from src/org/jblas/la/MatrixFunctions.java
rename to src/org/jblas/MatrixFunctions.java
index a82b59b..5235c52 100644
--- a/src/org/jblas/la/MatrixFunctions.java
+++ b/src/org/jblas/MatrixFunctions.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
  
 import java.lang.Math;
 
@@ -393,6 +393,26 @@ public class MatrixFunctions {
     public static double tan(double x) { return (double)Math.tan(x); }
     public static double tanh(double x) { return (double)Math.tanh(x); }
 //RJPP-END--------------------------------------------------------------
+
+//STOP
+    public static DoubleMatrix floatToDouble(FloatMatrix fm) {
+    	DoubleMatrix dm = new DoubleMatrix(fm.rows, fm.columns);
+
+        for (int i = 0; i < fm.length; i++)
+            dm.put(i, (double) fm.get(i));
+
+        return dm;
+    }
+
+    public static FloatMatrix doubleToFloat(DoubleMatrix dm) {
+        FloatMatrix fm = new FloatMatrix(dm.rows, dm.columns);
+
+        for (int i = 0; i < dm.length; i++)
+            fm.put(i, (float) dm.get(i));
+
+        return fm;
+    }
+//START
     
 //BEGIN
   // The code below has been automatically generated.
@@ -745,6 +765,7 @@ public class MatrixFunctions {
     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/Blas.java b/src/org/jblas/NativeBlas.java
similarity index 85%
rename from src/org/jblas/la/Blas.java
rename to src/org/jblas/NativeBlas.java
index 6d7c62d..1fb064c 100644
--- a/src/org/jblas/la/Blas.java
+++ b/src/org/jblas/NativeBlas.java
@@ -34,12 +34,43 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.core.ComplexFloat;
-import org.jblas.core.ComplexDouble;
-
-public class Blas {
+/**
+ * Native BLAS and LAPACK functions.
+ *
+ * <p>The NativeBlas class contains the native BLAS and LAPACK functions. Each
+ * Fortran function is mapped to a static method of this class. For each array argument,
+ * an additional parameter is introduced which gives the offset from the beginning of
+ * the passed array. In C, you would be able to pass a different pointer, but
+ * in Java, you can only pass the whole array.</p>
+ *
+ * <p>Note that due to the way the JNI is usually implemented, the arrays are first
+ * copied outside of the JVM before the function is called. This means that
+ * functions whose runtime is linear in the amount of memory do usually not
+ * run faster just because you are using a native implementation. This holds true
+ * for most Level 1 BLAS routines (like vector addition), and unfortunately also
+ * for most Level 2 BLAS routines (like matrix-vector multiplication). For these,
+ * there exists a class JavaBlas which contains Java implementations.</p>
+ *
+ * <p>In LAPACK, there exist routines which require workspace to be allocated together
+ * with a standard procedure for computing the size of these workspaces. jblas
+ * automatically also generates wrappers for these routines with automatic
+ * workspace allocation. These routines have the same name, but the workspace
+ * arguments are removed.</p>
+ *
+ * <p>Finally, an example: The fortran routine<pre>
+ * SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY)
+ *     DOUBLE PRECISION DA
+ *     INTEGER INCX,INCY,N
+ *     DOUBLE PRECISION DX(*),DY(*)
+ * </pre>
+ * becomes <pre>
+ * public static native void daxpy(int n, double da, double[] dx, int dxIdx,
+ *    int incx, double[] dy, int dyIdx, int incy);
+ * </pre>
+ */
+public class NativeBlas {
 
   static {
 	  try {
@@ -54,6 +85,10 @@ public class Blas {
 	  }
   } 
 
+  private static int[] intDummy = new int[1];
+  private static double[] doubleDummy = new double[1];
+  private static float[] floatDummy = new float[1];
+
   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);
@@ -105,7 +140,6 @@ public class Blas {
   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);
@@ -137,7 +171,6 @@ public class Blas {
   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);
@@ -209,7 +242,7 @@ public class Blas {
     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);
+    info = dsysv(uplo, n, nrhs, doubleDummy, 0, lda, intDummy, 0, doubleDummy, 0, ldb, work, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new double[lwork];
@@ -222,7 +255,7 @@ public class Blas {
     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);
+    info = ssysv(uplo, n, nrhs, floatDummy, 0, lda, intDummy, 0, floatDummy, 0, ldb, work, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new float[lwork];
@@ -235,7 +268,7 @@ public class Blas {
     int info;
     double[] work = new double[1];
     int lwork;
-    info = dsyev(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, -1);
+    info = dsyev(jobz, uplo, n, doubleDummy, 0, lda, doubleDummy, 0, work, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new double[lwork];
@@ -248,7 +281,7 @@ public class Blas {
     int info;
     float[] work = new float[1];
     int lwork;
-    info = ssyev(jobz, uplo, n, a, aIdx, lda, w, wIdx, work, 0, -1);
+    info = ssyev(jobz, uplo, n, floatDummy, 0, lda, floatDummy, 0, work, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new float[lwork];
@@ -263,7 +296,7 @@ public class Blas {
     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);
+    info = dsyevd(jobz, uplo, n, doubleDummy, 0, lda, doubleDummy, 0, work, 0, -1, iwork, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new double[lwork];
@@ -279,7 +312,7 @@ public class Blas {
     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);
+    info = dsyevr(jobz, range, uplo, n, doubleDummy, 0, lda, vl, vu, il, iu, abstol, intDummy, 0, doubleDummy, 0, doubleDummy, 0, ldz, intDummy, 0, work, 0, -1, iwork, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new double[lwork];
@@ -293,7 +326,7 @@ public class Blas {
     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);
+    info = dsyevx(jobz, range, uplo, n, doubleDummy, 0, lda, vl, vu, il, iu, abstol, intDummy, 0, doubleDummy, 0, doubleDummy, 0, ldz, work, 0, -1, intDummy, 0, intDummy, 0);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new double[lwork];
@@ -308,7 +341,7 @@ public class Blas {
     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);
+    info = ssyevd(jobz, uplo, n, floatDummy, 0, lda, floatDummy, 0, work, 0, -1, iwork, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new float[lwork];
@@ -324,7 +357,7 @@ public class Blas {
     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);
+    info = ssyevr(jobz, range, uplo, n, floatDummy, 0, lda, vl, vu, il, iu, abstol, intDummy, 0, floatDummy, 0, floatDummy, 0, ldz, intDummy, 0, work, 0, -1, iwork, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new float[lwork];
@@ -338,7 +371,7 @@ public class Blas {
     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);
+    info = ssyevx(jobz, range, uplo, n, floatDummy, 0, lda, vl, vu, il, iu, abstol, intDummy, 0, floatDummy, 0, floatDummy, 0, ldz, work, 0, -1, intDummy, 0, intDummy, 0);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new float[lwork];
@@ -348,12 +381,25 @@ public class Blas {
 
   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 cgeev(char jobvl, char jobvr, int n, float[] a, int aIdx, int lda, float[] w, int wIdx, float[] vl, int vlIdx, int ldvl, float[] vr, int vrIdx, int ldvr, float[] work, int workIdx, int lwork, float[] rwork, int rworkIdx);
+  public static int cgeev(char jobvl, char jobvr, int n, float[] a, int aIdx, int lda, float[] w, int wIdx, float[] vl, int vlIdx, int ldvl, float[] vr, int vrIdx, int ldvr, float[] rwork, int rworkIdx) {
+    int info;
+    float[] work = new float[1];
+    int lwork;
+    info = cgeev(jobvl, jobvr, n, floatDummy, 0, lda, floatDummy, 0, floatDummy, 0, ldvl, floatDummy, 0, ldvr, work, 0, -1, floatDummy, 0);
+    if (info != 0)
+      return info;
+    lwork = (int) work[0]; work = new float[lwork];
+    info = cgeev(jobvl, jobvr, n, a, aIdx, lda, w, wIdx, vl, vlIdx, ldvl, vr, vrIdx, ldvr, work, 0, lwork, rwork, rworkIdx);
+    return info;
+  }
+
   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);
+    info = dgeev(jobvl, jobvr, n, doubleDummy, 0, lda, doubleDummy, 0, doubleDummy, 0, doubleDummy, 0, ldvl, doubleDummy, 0, ldvr, work, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new double[lwork];
@@ -366,7 +412,7 @@ public class Blas {
     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);
+    info = sgeev(jobvl, jobvr, n, floatDummy, 0, lda, floatDummy, 0, floatDummy, 0, floatDummy, 0, ldvl, floatDummy, 0, ldvr, work, 0, -1);
     if (info != 0)
       return info;
     lwork = (int) work[0]; work = new float[lwork];
@@ -374,5 +420,22 @@ public class Blas {
     return info;
   }
 
+  public static native int zgeev(char jobvl, char jobvr, int n, double[] a, int aIdx, int lda, double[] w, int wIdx, double[] vl, int vlIdx, int ldvl, double[] vr, int vrIdx, int ldvr, double[] work, int workIdx, int lwork, double[] rwork, int rworkIdx);
+  public static int zgeev(char jobvl, char jobvr, int n, double[] a, int aIdx, int lda, double[] w, int wIdx, double[] vl, int vlIdx, int ldvl, double[] vr, int vrIdx, int ldvr, double[] rwork, int rworkIdx) {
+    int info;
+    double[] work = new double[1];
+    int lwork;
+    info = zgeev(jobvl, jobvr, n, doubleDummy, 0, lda, doubleDummy, 0, doubleDummy, 0, ldvl, doubleDummy, 0, ldvr, work, 0, -1, doubleDummy, 0);
+    if (info != 0)
+      return info;
+    lwork = (int) work[0]; work = new double[lwork];
+    info = zgeev(jobvl, jobvr, n, a, aIdx, lda, w, wIdx, vl, vlIdx, ldvl, vr, vrIdx, ldvr, work, 0, lwork, rwork, rworkIdx);
+    return info;
+  }
+
+  public static native int dgetrf(int m, int n, double[] a, int aIdx, int lda, int[] ipiv, int ipivIdx);
+  public static native int sgetrf(int m, int n, float[] a, int aIdx, int lda, int[] ipiv, int ipivIdx);
+  public static native int dpotrf(char uplo, int n, double[] a, int aIdx, int lda);
+  public static native int spotrf(char uplo, int n, float[] a, int aIdx, int lda);
 
 }
diff --git a/src/org/jblas/la/SimpleBlas.java b/src/org/jblas/SimpleBlas.java
similarity index 72%
rename from src/org/jblas/la/SimpleBlas.java
rename to src/org/jblas/SimpleBlas.java
index ff140fb..d893bf4 100644
--- a/src/org/jblas/la/SimpleBlas.java
+++ b/src/org/jblas/SimpleBlas.java
@@ -34,13 +34,12 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-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 org.jblas.exceptions.LapackException;
+import org.jblas.exceptions.LapackArgumentException;
+import org.jblas.exceptions.LapackConvergenceException;
+import org.jblas.exceptions.LapackSingularityException;
 
 //import edu.ida.core.OutputValue;
 
@@ -61,79 +60,79 @@ public class SimpleBlas {
 
 	/** 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);
+		//NativeBlas.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);
+		NativeBlas.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);
+		NativeBlas.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);
+		//NativeBlas.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);
+		NativeBlas.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);
+		//NativeBlas.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);
+		NativeBlas.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 NativeBlas.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);
+		return NativeBlas.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);
+		return NativeBlas.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);
+		return NativeBlas.dnrm2(x.length, x.data, 0, 1);
 	}
 	
 	public static double nrm2(ComplexDoubleMatrix x) {
-		return Blas.dznrm2(x.length, x.data, 0, 1);
+		return NativeBlas.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);
+		return NativeBlas.dasum(x.length, x.data, 0, 1);
 	}
 
 	public static double asum(ComplexDoubleMatrix x) {
-		return Blas.dzasum(x.length, x.data, 0, 1);
+		return NativeBlas.dzasum(x.length, x.data, 0, 1);
 	}
 
 	/**
@@ -141,11 +140,11 @@ public class SimpleBlas {
 	 * value maximum)
 	 */
 	public static int iamax(DoubleMatrix x) {
-		return Blas.idamax(x.length, x.data, 0, 1) - 1;
+		return NativeBlas.idamax(x.length, x.data, 0, 1) - 1;
 	}
 
 	public static int iamax(ComplexDoubleMatrix x) {
-		return Blas.izamax(x.length, x.data, 0, 1);
+		return NativeBlas.izamax(x.length, x.data, 0, 1);
 	}
 
 	/***************************************************************************
@@ -159,7 +158,7 @@ public class SimpleBlas {
 	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,
+		NativeBlas.dgemv('N', a.rows, a.columns, alpha, a.data, 0, a.rows, x.data, 0,
 				1, beta, y.data, 0, 1);
             }
             else {
@@ -167,14 +166,21 @@ public class SimpleBlas {
                     for (int i = 0; i < y.length; i++)
                         y.data[i] = 0.0;
                     
-                        for (int j = 0; j < a.columns; j++)
+                    for (int j = 0; j < a.columns; j++) {
+                        double xj = x.get(j);
+                        if (xj != 0.0) {
                             for (int i = 0; i < a.rows; i++)
-                                y.data[i] += a.get(i, j) * x.get(j);
+                                y.data[i] += a.get(i, j) * xj;
+                        }
+                    }
                 }
                 else {
-                     for (int j = 0; j < a.columns; j++)
+                     for (int j = 0; j < a.columns; j++) {
+                         double byj = beta * y.data[j];
+                         double xj = x.get(j);
                          for (int i = 0; i < a.rows; i++)
-                              y.data[j] = a.get(i, j) * x.get(i) + y.data[j];                    
+                              y.data[j] = a.get(i, j) * xj + byj;
+                     }
                 }
             }
 	    return y;
@@ -183,7 +189,7 @@ public class SimpleBlas {
 	/** 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,
+		NativeBlas.dger(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
 				0, a.rows);
 		return a;
 	}
@@ -191,7 +197,7 @@ public class SimpleBlas {
 	/** 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,
+		NativeBlas.zgeru(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
 				0, a.rows);
 		return a;
 	}
@@ -199,7 +205,7 @@ public class SimpleBlas {
 	/** 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,
+		NativeBlas.zgerc(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
 				0, a.rows);
 		return a;
 	}
@@ -214,14 +220,14 @@ public class SimpleBlas {
 	 */
 	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,
+		NativeBlas.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,
+		NativeBlas.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;
 	}
@@ -231,7 +237,7 @@ public class SimpleBlas {
 	 */
 	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,
+		int info = NativeBlas.dgesv(a.rows, b.columns, a.data, 0, a.rows, ipiv, 0,
 				b.data, 0, b.rows);
 		checkInfo("DGESV", info);
 
@@ -251,33 +257,22 @@ public class SimpleBlas {
 
 	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,
+		int info = NativeBlas.dsysv(uplo, a.rows, b.columns, a.data, 0, a.rows, ipiv, 0,
 				b.data, 0, b.rows);
-		checkInfo("DSYSV", info);
+		checkInfo("SYSV", info);
 
 		if (info > 0)
-			throw new IllegalArgumentException(
+			throw new LapackSingularityException("SYV",
 					"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);
+		int info = NativeBlas.dsyev(jobz, uplo, a.rows, a.data, 0, a.rows, w.data, 0);
 
 		if (info > 0)
-			throw new IllegalArgumentException(
+			throw new LapackConvergenceException("SYEV",
 					"Eigenvalues could not be computed " + info
 							+ " off-diagonal elements did not converge");
 
@@ -293,11 +288,9 @@ public class SimpleBlas {
         int[] m = new int[1];
         int info;
 
-		info = Blas.dsyevx(jobz, range, uplo, n, a.data, 0, a.rows, vl, vu, il,
+		info = NativeBlas.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
@@ -308,7 +301,7 @@ public class SimpleBlas {
 				msg.append(ifail[i]);
 			}
 			msg.append(".");
-			throw new IllegalArgumentException(msg.toString());
+			throw new LapackConvergenceException("SYEVX", msg.toString());
 		}
 
 		return info;
@@ -318,7 +311,7 @@ public class SimpleBlas {
 			DoubleMatrix w) {
 		int n = A.rows;
 
-		int info = Blas.dsyevd(jobz, uplo, n, A.data, 0, A.rows, w.data, 0);
+		int info = NativeBlas.dsyevd(jobz, uplo, n, A.data, 0, A.rows, w.data, 0);
 
 		if (info > 0)
 			throw new LapackConvergenceException("SYEVD", "Not all eigenvalues converged.");
@@ -332,11 +325,9 @@ public class SimpleBlas {
 		int n = a.rows;
         int[] m = new int[1];
 
-		int info = Blas.dsyevr(jobz, range, uplo, n, a.data, 0, a.rows, vl, vu,
+		int info = NativeBlas.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;
@@ -345,20 +336,20 @@ public class SimpleBlas {
 	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,
+		int info = NativeBlas.dposv(uplo, n, nrhs, A.data, 0, A.rows, B.data, 0,
 				B.rows);
 		checkInfo("DPOSV", info);
 		if (info > 0)
-			throw new LapackException("DPOSV",
+			throw new LapackArgumentException("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, 
+            int info = NativeBlas.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.");
+                throw new LapackConvergenceException("DGEEV", "First " + info + " eigenvalues have not converged.");
             return info;
         }
 
@@ -371,79 +362,79 @@ public class SimpleBlas {
 
 	/** 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);
+		//NativeBlas.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);
+		NativeBlas.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);
+		NativeBlas.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);
+		//NativeBlas.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);
+		NativeBlas.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);
+		//NativeBlas.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);
+		NativeBlas.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 NativeBlas.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);
+		return NativeBlas.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);
+		return NativeBlas.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);
+		return NativeBlas.snrm2(x.length, x.data, 0, 1);
 	}
 	
 	public static float nrm2(ComplexFloatMatrix x) {
-		return Blas.scnrm2(x.length, x.data, 0, 1);
+		return NativeBlas.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);
+		return NativeBlas.sasum(x.length, x.data, 0, 1);
 	}
 
 	public static float asum(ComplexFloatMatrix x) {
-		return Blas.scasum(x.length, x.data, 0, 1);
+		return NativeBlas.scasum(x.length, x.data, 0, 1);
 	}
 
 	/**
@@ -451,11 +442,11 @@ public class SimpleBlas {
 	 * value maximum)
 	 */
 	public static int iamax(FloatMatrix x) {
-		return Blas.isamax(x.length, x.data, 0, 1) - 1;
+		return NativeBlas.isamax(x.length, x.data, 0, 1) - 1;
 	}
 
 	public static int iamax(ComplexFloatMatrix x) {
-		return Blas.icamax(x.length, x.data, 0, 1);
+		return NativeBlas.icamax(x.length, x.data, 0, 1);
 	}
 
 	/***************************************************************************
@@ -469,7 +460,7 @@ public class SimpleBlas {
 	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,
+		NativeBlas.sgemv('N', a.rows, a.columns, alpha, a.data, 0, a.rows, x.data, 0,
 				1, beta, y.data, 0, 1);
             }
             else {
@@ -477,14 +468,21 @@ public class SimpleBlas {
                     for (int i = 0; i < y.length; i++)
                         y.data[i] = 0.0f;
                     
-                        for (int j = 0; j < a.columns; j++)
+                    for (int j = 0; j < a.columns; j++) {
+                        float xj = x.get(j);
+                        if (xj != 0.0f) {
                             for (int i = 0; i < a.rows; i++)
-                                y.data[i] += a.get(i, j) * x.get(j);
+                                y.data[i] += a.get(i, j) * xj;
+                        }
+                    }
                 }
                 else {
-                     for (int j = 0; j < a.columns; j++)
+                     for (int j = 0; j < a.columns; j++) {
+                         float byj = beta * y.data[j];
+                         float xj = x.get(j);
                          for (int i = 0; i < a.rows; i++)
-                              y.data[j] = a.get(i, j) * x.get(i) + y.data[j];                    
+                              y.data[j] = a.get(i, j) * xj + byj;
+                     }
                 }
             }
 	    return y;
@@ -493,7 +491,7 @@ public class SimpleBlas {
 	/** 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,
+		NativeBlas.sger(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
 				0, a.rows);
 		return a;
 	}
@@ -501,7 +499,7 @@ public class SimpleBlas {
 	/** 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,
+		NativeBlas.cgeru(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
 				0, a.rows);
 		return a;
 	}
@@ -509,7 +507,7 @@ public class SimpleBlas {
 	/** 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,
+		NativeBlas.cgerc(a.rows, a.columns, alpha, x.data, 0, 1, y.data, 0, 1, a.data,
 				0, a.rows);
 		return a;
 	}
@@ -524,14 +522,14 @@ public class SimpleBlas {
 	 */
 	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,
+		NativeBlas.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,
+		NativeBlas.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;
 	}
@@ -541,7 +539,7 @@ public class SimpleBlas {
 	 */
 	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,
+		int info = NativeBlas.sgesv(a.rows, b.columns, a.data, 0, a.rows, ipiv, 0,
 				b.data, 0, b.rows);
 		checkInfo("DGESV", info);
 
@@ -555,33 +553,22 @@ public class SimpleBlas {
 
 	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,
+		int info = NativeBlas.ssysv(uplo, a.rows, b.columns, a.data, 0, a.rows, ipiv, 0,
 				b.data, 0, b.rows);
-		checkInfo("DSYSV", info);
+		checkInfo("SYSV", info);
 
 		if (info > 0)
-			throw new IllegalArgumentException(
+			throw new LapackSingularityException("SYV",
 					"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);
+		int info = NativeBlas.ssyev(jobz, uplo, a.rows, a.data, 0, a.rows, w.data, 0);
 
 		if (info > 0)
-			throw new IllegalArgumentException(
+			throw new LapackConvergenceException("SYEV",
 					"Eigenvalues could not be computed " + info
 							+ " off-diagonal elements did not converge");
 
@@ -597,11 +584,9 @@ public class SimpleBlas {
         int[] m = new int[1];
         int info;
 
-		info = Blas.ssyevx(jobz, range, uplo, n, a.data, 0, a.rows, vl, vu, il,
+		info = NativeBlas.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
@@ -612,7 +597,7 @@ public class SimpleBlas {
 				msg.append(ifail[i]);
 			}
 			msg.append(".");
-			throw new IllegalArgumentException(msg.toString());
+			throw new LapackConvergenceException("SYEVX", msg.toString());
 		}
 
 		return info;
@@ -622,7 +607,7 @@ public class SimpleBlas {
 			FloatMatrix w) {
 		int n = A.rows;
 
-		int info = Blas.ssyevd(jobz, uplo, n, A.data, 0, A.rows, w.data, 0);
+		int info = NativeBlas.ssyevd(jobz, uplo, n, A.data, 0, A.rows, w.data, 0);
 
 		if (info > 0)
 			throw new LapackConvergenceException("SYEVD", "Not all eigenvalues converged.");
@@ -636,11 +621,9 @@ public class SimpleBlas {
 		int n = a.rows;
         int[] m = new int[1];
 
-		int info = Blas.ssyevr(jobz, range, uplo, n, a.data, 0, a.rows, vl, vu,
+		int info = NativeBlas.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;
@@ -649,20 +632,20 @@ public class SimpleBlas {
 	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,
+		int info = NativeBlas.sposv(uplo, n, nrhs, A.data, 0, A.rows, B.data, 0,
 				B.rows);
 		checkInfo("DPOSV", info);
 		if (info > 0)
-			throw new LapackException("DPOSV",
+			throw new LapackArgumentException("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, 
+            int info = NativeBlas.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.");
+                throw new LapackConvergenceException("DGEEV", "First " + info + " eigenvalues have not converged.");
             return info;
         }
 
diff --git a/src/org/jblas/la/Solve.java b/src/org/jblas/Solve.java
similarity index 99%
rename from src/org/jblas/la/Solve.java
rename to src/org/jblas/Solve.java
index cf6830e..076f6b2 100644
--- a/src/org/jblas/la/Solve.java
+++ b/src/org/jblas/Solve.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 /**
  * Solving linear equations.
diff --git a/src/org/jblas/la/Trigonometry.java b/src/org/jblas/Trigonometry.java
similarity index 98%
rename from src/org/jblas/la/Trigonometry.java
rename to src/org/jblas/Trigonometry.java
index 1ec4768..3f6139d 100644
--- a/src/org/jblas/la/Trigonometry.java
+++ b/src/org/jblas/Trigonometry.java
@@ -34,34 +34,34 @@
  */
 // --- 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
-}
+/*
+ * 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;
+
+/**
+ * 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/exceptions/LapackArgumentException.java
similarity index 94%
rename from src/org/jblas/la/exceptions/LapackArgumentException.java
rename to src/org/jblas/exceptions/LapackArgumentException.java
index 376bc68..d408823 100644
--- a/src/org/jblas/la/exceptions/LapackArgumentException.java
+++ b/src/org/jblas/exceptions/LapackArgumentException.java
@@ -34,19 +34,23 @@
  */
 // --- 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.");
-	}
-}
+package org.jblas.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.");
+	}
+
+    public LapackArgumentException(String function, String message) {
+        super(function, message);
+    }
+}
diff --git a/src/org/jblas/la/exceptions/LapackConvergenceException.java b/src/org/jblas/exceptions/LapackConvergenceException.java
similarity index 98%
rename from src/org/jblas/la/exceptions/LapackConvergenceException.java
rename to src/org/jblas/exceptions/LapackConvergenceException.java
index 23b1703..a8b3056 100644
--- a/src/org/jblas/la/exceptions/LapackConvergenceException.java
+++ b/src/org/jblas/exceptions/LapackConvergenceException.java
@@ -39,7 +39,7 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la.exceptions;
+package org.jblas.exceptions;
 
 /**
  *
diff --git a/src/org/jblas/la/exceptions/LapackException.java b/src/org/jblas/exceptions/LapackException.java
similarity index 97%
rename from src/org/jblas/la/exceptions/LapackException.java
rename to src/org/jblas/exceptions/LapackException.java
index 5ebd04a..87a9e79 100644
--- a/src/org/jblas/la/exceptions/LapackException.java
+++ b/src/org/jblas/exceptions/LapackException.java
@@ -34,20 +34,20 @@
  */
 // --- 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);
-	}
-}
+package org.jblas.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/exceptions/LapackPositivityException.java b/src/org/jblas/exceptions/LapackPositivityException.java
new file mode 100644
index 0000000..d8819fa
--- /dev/null
+++ b/src/org/jblas/exceptions/LapackPositivityException.java
@@ -0,0 +1,15 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.exceptions;
+
+/**
+ *
+ */
+public class LapackPositivityException extends LapackException {
+    public LapackPositivityException(String fct, String msg) {
+        super(fct, msg);
+    }
+}
diff --git a/src/org/jblas/la/FloatFunction.java b/src/org/jblas/exceptions/LapackSingularityException.java
similarity index 87%
rename from src/org/jblas/la/FloatFunction.java
rename to src/org/jblas/exceptions/LapackSingularityException.java
index 150e58c..fb766b0 100644
--- a/src/org/jblas/la/FloatFunction.java
+++ b/src/org/jblas/exceptions/LapackSingularityException.java
@@ -34,12 +34,13 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas.exceptions;
 
 /**
- * Represents a function on floats.
+ * Exception thrown when matrices are singular.
  */
-public interface FloatFunction {
-        /** Compute the function. */
-	public float compute(float x);
+public class LapackSingularityException extends LapackException {
+    public LapackSingularityException(String fct, String msg) {
+        super(fct, msg);
+    }
 }
diff --git a/src/org/jblas/la/exceptions/SizeException.java b/src/org/jblas/exceptions/SizeException.java
similarity index 98%
rename from src/org/jblas/la/exceptions/SizeException.java
rename to src/org/jblas/exceptions/SizeException.java
index 2287fa6..96dd8ac 100644
--- a/src/org/jblas/la/exceptions/SizeException.java
+++ b/src/org/jblas/exceptions/SizeException.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la.exceptions;
+package org.jblas.exceptions;
 
 public class SizeException extends RuntimeException {
 	public SizeException(String message) {
diff --git a/src/org/jblas/core/package-info.java b/src/org/jblas/exceptions/package-info.java
similarity index 92%
rename from src/org/jblas/core/package-info.java
rename to src/org/jblas/exceptions/package-info.java
index 0f9901a..dcb6d0d 100644
--- a/src/org/jblas/core/package-info.java
+++ b/src/org/jblas/exceptions/package-info.java
@@ -35,8 +35,7 @@
 // --- END LICENSE BLOCK ---
 
 /**
- * Support classes for jBLAS.
- * 
- * This package contains several base classes, for example complex data types.
+ * jblas related exceptions.
  */
-package org.jblas.core;
+
+package org.jblas.exceptions;
diff --git a/src/org/jblas/la/exceptions/package-info.java b/src/org/jblas/la/exceptions/package-info.java
deleted file mode 100644
index 13d918c..0000000
--- a/src/org/jblas/la/exceptions/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * jblas related exceptions.
- */
-
-package org.jblas.la.exceptions;
\ No newline at end of file
diff --git a/src/org/jblas/la/ranges/package-info.java b/src/org/jblas/la/ranges/package-info.java
deleted file mode 100644
index 2a9747b..0000000
--- a/src/org/jblas/la/ranges/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * Provide ways to specify indices ranges.
- */
-
-package org.jblas.la.ranges;
\ No newline at end of file
diff --git a/src/org/jblas/la/package-info.java b/src/org/jblas/package-info.java
similarity index 98%
copy from src/org/jblas/la/package-info.java
copy to src/org/jblas/package-info.java
index 34c96f9..1a254a7 100644
--- a/src/org/jblas/la/package-info.java
+++ b/src/org/jblas/package-info.java
@@ -39,4 +39,4 @@
  * 
  * This package contains the linear algebra packages from jBLAS.
  */
-package org.jblas.la;
+package org.jblas;
diff --git a/src/org/jblas/la/ranges/AllRange.java b/src/org/jblas/ranges/AllRange.java
similarity index 98%
rename from src/org/jblas/la/ranges/AllRange.java
rename to src/org/jblas/ranges/AllRange.java
index 101f5af..9fe1d78 100644
--- a/src/org/jblas/la/ranges/AllRange.java
+++ b/src/org/jblas/ranges/AllRange.java
@@ -39,9 +39,9 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la.ranges;
+package org.jblas.ranges;
 
-import org.jblas.la.*;
+import org.jblas.*;
 
 /**
  * A range over all available indices. Can be used to address whole columns or rows. Like
diff --git a/src/org/jblas/la/ranges/IndicesRange.java b/src/org/jblas/ranges/IndicesRange.java
similarity index 98%
rename from src/org/jblas/la/ranges/IndicesRange.java
rename to src/org/jblas/ranges/IndicesRange.java
index fffa712..a7bbcea 100644
--- a/src/org/jblas/la/ranges/IndicesRange.java
+++ b/src/org/jblas/ranges/IndicesRange.java
@@ -39,9 +39,9 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la.ranges;
+package org.jblas.ranges;
 
-import org.jblas.la.*;
+import org.jblas.*;
 
 /**
  * Range which varies over pre-specified indices.
diff --git a/src/org/jblas/la/ranges/IntervalRange.java b/src/org/jblas/ranges/IntervalRange.java
similarity index 98%
rename from src/org/jblas/la/ranges/IntervalRange.java
rename to src/org/jblas/ranges/IntervalRange.java
index 909c639..beaf0e4 100644
--- a/src/org/jblas/la/ranges/IntervalRange.java
+++ b/src/org/jblas/ranges/IntervalRange.java
@@ -38,7 +38,7 @@
  * To change this template, choose Tools | Templates
  * and open the template in the editor.
  */
-package org.jblas.la.ranges;
+package org.jblas.ranges;
 
 /**
  * Range which varies from a given interval. Endpoints are both inclusive!
diff --git a/src/org/jblas/la/ranges/PointRange.java b/src/org/jblas/ranges/PointRange.java
similarity index 98%
rename from src/org/jblas/la/ranges/PointRange.java
rename to src/org/jblas/ranges/PointRange.java
index a14ec86..b6d546a 100644
--- a/src/org/jblas/la/ranges/PointRange.java
+++ b/src/org/jblas/ranges/PointRange.java
@@ -39,7 +39,7 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la.ranges;
+package org.jblas.ranges;
 
 /**
  * A PointRange is a range which only has a single point.
diff --git a/src/org/jblas/la/ranges/Range.java b/src/org/jblas/ranges/Range.java
similarity index 99%
rename from src/org/jblas/la/ranges/Range.java
rename to src/org/jblas/ranges/Range.java
index ef784b1..24564c4 100644
--- a/src/org/jblas/la/ranges/Range.java
+++ b/src/org/jblas/ranges/Range.java
@@ -39,7 +39,7 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la.ranges;
+package org.jblas.ranges;
 
 /**
  * <p>The Range interface represents basically a set of indices. Before using a range
diff --git a/src/org/jblas/la/ranges/RangeUtils.java b/src/org/jblas/ranges/RangeUtils.java
similarity index 95%
rename from src/org/jblas/la/ranges/RangeUtils.java
rename to src/org/jblas/ranges/RangeUtils.java
index 7a5ece9..4fded9a 100644
--- a/src/org/jblas/la/ranges/RangeUtils.java
+++ b/src/org/jblas/ranges/RangeUtils.java
@@ -39,11 +39,9 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la.ranges;
+package org.jblas.ranges;
 
-import org.jblas.la.*;
-import org.jblas.la.ranges.IndicesRange;
-import org.jblas.la.ranges.AllRange;
+import org.jblas.*;
 
 /**
  * A bunch of static functions for making construction of ranges more
diff --git a/src/org/jblas/la/package-info.java b/src/org/jblas/ranges/package-info.java
similarity index 93%
rename from src/org/jblas/la/package-info.java
rename to src/org/jblas/ranges/package-info.java
index 34c96f9..0fde3cd 100644
--- a/src/org/jblas/la/package-info.java
+++ b/src/org/jblas/ranges/package-info.java
@@ -35,8 +35,7 @@
 // --- END LICENSE BLOCK ---
 
 /**
- * Main linear algebra package.
- * 
- * This package contains the linear algebra packages from jBLAS.
+ * Provide ways to specify indices ranges.
  */
-package org.jblas.la;
+
+package org.jblas.ranges;
diff --git a/src/org/jblas/core/Functions.java b/src/org/jblas/util/Functions.java
similarity index 92%
rename from src/org/jblas/core/Functions.java
rename to src/org/jblas/util/Functions.java
index 8573ea8..d2d9440 100644
--- a/src/org/jblas/core/Functions.java
+++ b/src/org/jblas/util/Functions.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.core;
+package org.jblas.util;
 
 public class Functions {
 	public static double sinc(double x) {
@@ -43,4 +43,7 @@ public class Functions {
 		else
 			return Math.sin(Math.PI * x) / (Math.PI * x);
 	}
+
+    public static int min(int a, int b) { return a < b ? a : b; }
+    public static int max(int a, int b) { return a > b ? a : b; }
 }
diff --git a/src/org/jblas/util/LibraryLoader.java b/src/org/jblas/util/LibraryLoader.java
index 91d73f3..f54a188 100644
--- a/src/org/jblas/util/LibraryLoader.java
+++ b/src/org/jblas/util/LibraryLoader.java
@@ -33,7 +33,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 // --- END LICENSE BLOCK ---
-
 package org.jblas.util;
 
 import java.io.*;
@@ -43,69 +42,94 @@ import java.io.*;
  * 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;
+    /** 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
+     * @throws UnsatisfiedLinkError if library cannot be founds
+     */
+    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();
+
+        // Trying to copy from here.
+        System.err.println("Trying to copy from /" + libname + ".");
+        InputStream is = cl.getResourceAsStream("/" + libname);
+
+        // Trying to copy from "bin"
+        if (is == null) {
+            System.err.println("Trying to copy from /bin/" + libname + ".");
+            is = cl.getResourceAsStream("/bin/" + libname);
+        }
+
+        // Trying to extract static version from the jar file. Why the static version?
+        // Because it is more likely to run.
+        if (is == null) {
+            System.err.println("Trying to copy from " + fatJarLibraryPath(libname, "static") + ".");
+            is = cl.getResourceAsStream(fatJarLibraryPath(libname, "static"));
+        }
+
+        // Finally, let's see if we can get the dynamic version.
+        if (is == null) {
+            is = cl.getResourceAsStream(fatJarLibraryPath(libname, "dynamic"));
+            System.err.println("Trying to copy from " + fatJarLibraryPath(libname, "dynamic") + ".");
+        }
+
+        // Oh man, have to get out of here!
+        if (is == null) {
+            throw new UnsatisfiedLinkError("Couldn't find the resource " + libname + ".");
+        }
+
+        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.err.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");
+        }
     }
 
-    static public void main(String[] args) {
-        System.out.println(libraryPath(""));
+    static public String unifyOSName(String osname) {
+        if (osname.startsWith("Windows")) {
+            return "Windows";
+        }
+        return osname;
+    }
+
+    /** Compute the path to the library. The path is basically
+    "/" + os.name + "/" + os.arch + "/" + libname. */
+    static public String fatJarLibraryPath(String libname, String linkage) {
+        String sep = "/"; //System.getProperty("file.separator");
+        String os_name = unifyOSName(System.getProperty("os.name"));
+        String os_arch = System.getProperty("os.arch");
+        return sep + "lib" + sep + linkage + sep + os_name + sep + os_arch + sep + libname;
     }
 }
diff --git a/src/org/jblas/util/Permutations.java b/src/org/jblas/util/Permutations.java
new file mode 100644
index 0000000..40d9ebf
--- /dev/null
+++ b/src/org/jblas/util/Permutations.java
@@ -0,0 +1,86 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.jblas.util;
+
+import java.util.Random;
+import org.jblas.DoubleMatrix;
+
+/**
+ *
+ */
+public class Permutations {
+    /**
+     * Create a random permutation of the numbers 0, ..., size - 1.
+     *
+     * see Algorithm P, D.E. Knuth: The Art of Computer Programming, Vol. 2, p. 145
+     */
+    public static int[] randomPermutation(int size) {
+        Random r = new Random();
+        int[] result = new int[size];
+
+        for (int j = 0; j < size; j++) {
+            result[j] = j;
+        }
+        
+        for (int j = size - 1; j > 0; j--) {
+            int k = r.nextInt(j);
+            int temp = result[j];
+            result[j] = result[k];
+            result[k] = temp;
+        }
+
+        return result;
+    }
+    
+    /**
+     * Get a random sample of k out of n elements.
+     *
+     * See Algorithm S, D. E. Knuth, The Art of Computer Programming, Vol. 2, p.142.
+     */
+    public static int[] randomSubset(int k, int n) {
+        assert(0 < k && k <= n);
+        Random r = new Random();
+        int t = 0, m = 0;
+        int[] result = new int[k];
+
+        while (m < k) {
+            double u = r.nextDouble();
+            if ( (n - t) * u < k - m ) {
+                result[m] = t;
+                m++;
+            }
+            t++;
+        }
+        return result;
+    }
+
+    /**
+     * Create a permutation matrix from a LAPACK-style 'ipiv' vector.
+     *
+     * @param ipiv row i was interchanged with row ipiv[i]
+     */
+    public static DoubleMatrix permutationMatrixFromPivotIndices(int size, int[] ipiv) {
+        int n = ipiv.length;
+        //System.out.printf("size = %d n = %d\n", size, n);
+        int indices[] = new int[size];
+        for (int i = 0; i < size; i++)
+            indices[i] = i;
+
+        //for (int i = 0; i < n; i++)
+        //    System.out.printf("ipiv[%d] = %d\n", i, ipiv[i]);
+
+        for (int i = 0; i < n; i++) {
+            int j = ipiv[i] - 1;
+            int t = indices[i];
+            indices[i] = indices[j];
+            indices[j] = t;
+        }
+        DoubleMatrix result = new DoubleMatrix(size, size);
+        for (int i = 0; i < size; i++)
+            result.put(indices[i], i, 1.0);
+        return result;
+    }
+}
diff --git a/src/org/jblas/util/SanityChecks.java b/src/org/jblas/util/SanityChecks.java
new file mode 100644
index 0000000..95c192a
--- /dev/null
+++ b/src/org/jblas/util/SanityChecks.java
@@ -0,0 +1,83 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.jblas.util;
+
+import org.jblas.NativeBlas;
+import org.jblas.DoubleMatrix;
+
+/**
+ *
+ */
+public class SanityChecks {
+
+    public static int checksFailed;
+
+    public static void check(String message, boolean condition) {
+        System.out.print(message + "... ");
+        if (condition) {
+            System.out.println("ok");
+        } else {
+            System.out.println("failed");
+            checksFailed++;
+        }
+    }
+
+    public static void checkVectorAddition() {
+        DoubleMatrix x = new DoubleMatrix(3, 1, 1.0, 2.0, 3.0);
+        DoubleMatrix y = new DoubleMatrix(3, 1, 4.0, 5.0, 6.0);
+        DoubleMatrix z = new DoubleMatrix(3, 1, 5.0, 7.0, 9.0);
+
+        check("checking vector addition", x.add(y).equals(z));
+    }
+
+    public static void checkMatrixMultiplication() {
+
+        DoubleMatrix A = new DoubleMatrix(new double[][] {
+            { 1.0, 2.0, 3.0 },
+            { 4.0, 5.0, 6.0 },
+            { 7.0, 8.0, 9.0 }
+        });
+        DoubleMatrix E = new DoubleMatrix(new double[][] {
+            { 0.0, 0.0, 1.0 },
+            { 0.0, 1.0, 0.0 },
+            { 1.0, 0.0, 0.0 }
+        });
+        DoubleMatrix B = new DoubleMatrix(new double[][] {
+            { 3.0, 2.0, 1.0 },
+            { 6.0, 5.0, 4.0 },
+            { 9.0, 8.0, 7.0 }
+        });
+
+        check("checking matrix multiplication", A.mmul(E).equals(B));
+    }
+
+    public static void checkXerbla() {
+        double[] x = new double[9];
+        try {
+            NativeBlas.dgemm('N', 'N', 3, -1, 3, 1.0, x, 0, 3, x, 0, 3, 0.0, x, 0, 3);
+        }
+        catch(IllegalArgumentException e) {
+            check("checking XERBLA", e.getMessage().contains("XERBLA"));
+            return;
+        }
+        assert(false); // shouldn't happen
+    }
+
+    public static void main(String[] args) {
+        checkVectorAddition();
+        checkMatrixMultiplication();
+        checkXerbla();
+        printSummary();
+    }
+
+    private static void printSummary() {
+        if (checksFailed == 0) {
+            System.out.println("Sanity checks passed.");
+        }
+        else {
+            System.out.println("Sainty checks FAILED!");
+        }
+    }
+}
diff --git a/src/overview.html b/src/overview.html
index 8ade4de..9d4c83e 100644
--- a/src/overview.html
+++ b/src/overview.html
@@ -1,7 +1,7 @@
 <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>
+classes like <a href="org/jblas/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
@@ -9,14 +9,14 @@ 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
+	<li>There exist four classes: <a href="org/jblas/ComplexFloatMatrix.html">FloatMatrix</a>, <a href="org/jblas/DoubleMatrix.html">DoubleMatrix</a>,
+  <a href="org/jblas/ComplexFloatMatrix.html">ComplexFloatMatrix</a> and <a href="org/jblas/ComplexDoubleMatrix.html">ComplexDoubleMatrix</a> in the package
+  <code>org.jblas</code> 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>
+  eigenvalues are grouped in classes like <a href="org/jblas/Eigen.html">Eigen</a>, <a href="org/jblas/Solve.html">Solve</a>, or <a href="org/jblas/Geometry.html">Geometry</a>.</li>
 </ul>
 <ul>
 	<li>To construct a new matrix, you can either use the constructor, or
diff --git a/src/overview.textile b/src/overview.textile
index 500191b..cfd0db3 100644
--- a/src/overview.textile
+++ b/src/overview.textile
@@ -14,7 +14,7 @@ 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
+  @org.jblas@ which represent real and complex matrices in single and
   double precision.
 
 * Higher-level routines for solving equations, or computing
diff --git a/test/org/jblas/la/BenchmarkAccess.java b/test/org/jblas/BenchmarkAccess.java
similarity index 95%
rename from test/org/jblas/la/BenchmarkAccess.java
rename to test/org/jblas/BenchmarkAccess.java
index df2b985..c0dd0cd 100644
--- a/test/org/jblas/la/BenchmarkAccess.java
+++ b/test/org/jblas/BenchmarkAccess.java
@@ -34,11 +34,11 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 import junit.framework.TestCase;
 
-import static org.jblas.la.TicToc.*;
+import static org.jblas.TicToc.*;
 
 public class BenchmarkAccess extends TestCase {
 	public void testArrayVsDirectBuffer() {
@@ -79,9 +79,9 @@ public class BenchmarkAccess extends TestCase {
 			}
 		toc();
 		
-		tic("Blas.dcopy");
+		tic("NativeBlas.dcopy");
 		for (int j = 0; j < ITERS; j++)
-			Blas.dcopy(SIZE, mb.data, 0, 1, ma.data, 0, 1);
+			NativeBlas.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/BenchmarkComplex.java
similarity index 96%
rename from test/org/jblas/la/BenchmarkComplex.java
rename to test/org/jblas/BenchmarkComplex.java
index 5958452..caf0aed 100644
--- a/test/org/jblas/la/BenchmarkComplex.java
+++ b/test/org/jblas/BenchmarkComplex.java
@@ -34,11 +34,10 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.ComplexDoubleMatrix;
 import junit.framework.TestCase;
-import static org.jblas.la.TicToc.*;
+import static org.jblas.TicToc.*;
 
 public class BenchmarkComplex extends TestCase {
     public void testMul() {
diff --git a/test/org/jblas/la/BenchmarkElementwise.java b/test/org/jblas/BenchmarkElementwise.java
similarity index 96%
rename from test/org/jblas/la/BenchmarkElementwise.java
rename to test/org/jblas/BenchmarkElementwise.java
index 283056d..7db70f6 100644
--- a/test/org/jblas/la/BenchmarkElementwise.java
+++ b/test/org/jblas/BenchmarkElementwise.java
@@ -34,11 +34,11 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 import junit.framework.TestCase;
-import static org.jblas.la.TicToc.*;
-import static org.jblas.la.DoubleMatrix.*;
+import static org.jblas.TicToc.*;
+import static org.jblas.DoubleMatrix.*;
 
 public class BenchmarkElementwise extends TestCase {
 	public void testMuli() {
diff --git a/test/org/jblas/la/BenchmarkMatrix.java b/test/org/jblas/BenchmarkMatrix.java
similarity index 97%
rename from test/org/jblas/la/BenchmarkMatrix.java
rename to test/org/jblas/BenchmarkMatrix.java
index 0676f49..7391322 100644
--- a/test/org/jblas/la/BenchmarkMatrix.java
+++ b/test/org/jblas/BenchmarkMatrix.java
@@ -39,14 +39,11 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la;
+package org.jblas;
 
-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.*;
+import static org.jblas.TicToc.*;
 
 /**
  *
diff --git a/test/org/jblas/la/ComplexDoubleMatrixTest.java b/test/org/jblas/ComplexDoubleMatrixTest.java
similarity index 95%
rename from test/org/jblas/la/ComplexDoubleMatrixTest.java
rename to test/org/jblas/ComplexDoubleMatrixTest.java
index cd3a566..ee32c1c 100644
--- a/test/org/jblas/la/ComplexDoubleMatrixTest.java
+++ b/test/org/jblas/ComplexDoubleMatrixTest.java
@@ -39,11 +39,8 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la;
+package org.jblas;
 
-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;
diff --git a/test/org/jblas/la/DemoImages.java b/test/org/jblas/DemoImages.java
similarity index 94%
rename from test/org/jblas/la/DemoImages.java
rename to test/org/jblas/DemoImages.java
index 53f6380..e1bc1f2 100644
--- a/test/org/jblas/la/DemoImages.java
+++ b/test/org/jblas/DemoImages.java
@@ -34,17 +34,15 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.DoubleMatrix;
-import org.jblas.la.Blas;
 import junit.framework.TestCase;
-import static org.jblas.la.TicToc.*;
+import static org.jblas.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 static org.jblas.MatrixFunctions.*;
 import java.util.Arrays;
 
 public class DemoImages extends TestCase {
@@ -62,7 +60,7 @@ public class DemoImages extends TestCase {
 
 	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);
+			NativeBlas.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) {
@@ -215,7 +213,7 @@ public class DemoImages extends TestCase {
 		
 		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, 
+			NativeBlas.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);
@@ -224,11 +222,11 @@ public class DemoImages extends TestCase {
 			// 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);
+				NativeBlas.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);
+			NativeBlas.dcopy(w.rows - w.columns, w.data, 0, 1, result.data, result.index(0, i), 1);
 		}
 		return result;
 	}
diff --git a/test/org/jblas/core/Dynamic.java b/test/org/jblas/Dynamic.java
similarity index 98%
rename from test/org/jblas/core/Dynamic.java
rename to test/org/jblas/Dynamic.java
index 76feaf6..2a1926f 100644
--- a/test/org/jblas/core/Dynamic.java
+++ b/test/org/jblas/Dynamic.java
@@ -34,16 +34,16 @@
  */
 // --- 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");
-	}
-}
+package org.jblas;
+
+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/la/SimpleBlasTest.java b/test/org/jblas/SimpleBlasTest.java
similarity index 96%
rename from test/org/jblas/la/SimpleBlasTest.java
rename to test/org/jblas/SimpleBlasTest.java
index d366d66..b2fb358 100644
--- a/test/org/jblas/la/SimpleBlasTest.java
+++ b/test/org/jblas/SimpleBlasTest.java
@@ -39,10 +39,8 @@
  * and open the template in the editor.
  */
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.SimpleBlas;
-import org.jblas.la.DoubleMatrix;
 import junit.framework.TestCase;
 
 /**
diff --git a/test/org/jblas/la/TestBlasDouble.java b/test/org/jblas/TestBlasDouble.java
similarity index 88%
rename from test/org/jblas/la/TestBlasDouble.java
rename to test/org/jblas/TestBlasDouble.java
index 690eba2..565a475 100644
--- a/test/org/jblas/la/TestBlasDouble.java
+++ b/test/org/jblas/TestBlasDouble.java
@@ -34,11 +34,11 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 import junit.framework.TestCase;
 
-import static org.jblas.la.MatrixFunctions.*;
+import static org.jblas.MatrixFunctions.*;
 
 public class TestBlasDouble extends TestCase {
 
@@ -46,9 +46,9 @@ public class TestBlasDouble extends TestCase {
 	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));
+		assertEquals(10.0, NativeBlas.dasum(4, a, 0, 1));
+		assertEquals(4.0, NativeBlas.dasum(2, a, 0, 2));
+		assertEquals(5.0, NativeBlas.dasum(2, a, 1, 1));
 	}
 	
 	/** test scalar product */
@@ -56,9 +56,9 @@ public class TestBlasDouble extends TestCase {
 		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));
+		assertEquals(32.0, NativeBlas.ddot(3, a, 0, 1, b, 0, 1));
+		assertEquals(22.0, NativeBlas.ddot(2, a, 0, 2, b, 0, 2));
+		assertEquals(5.0 + 12.0 + 21.0, NativeBlas.ddot(3, a, 0, 1, b, 1, 1));
 	}
 	
         public void testSwap() {
@@ -68,12 +68,12 @@ public class TestBlasDouble extends TestCase {
             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);
+            NativeBlas.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);
+            NativeBlas.dswap(2, a, 0, 2, a, 1, 2);
             assertTrue(arraysEqual(a, 5.0, 4.0, 7.0, 6.0));
         }
         
@@ -82,7 +82,7 @@ public class TestBlasDouble extends TestCase {
 		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);
+		NativeBlas.daxpy(4, 2.0, x, 0, 1, y, 0, 1);
 		
 		for(int i = 0; i < 4; i++)
 			assertEquals(2*x[i], y[i]);
@@ -97,7 +97,7 @@ public class TestBlasDouble extends TestCase {
 		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);
+		NativeBlas.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);
@@ -105,7 +105,7 @@ public class TestBlasDouble extends TestCase {
 		
 		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);
+		NativeBlas.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));
diff --git a/test/org/jblas/la/TestBlasDoubleComplex.java b/test/org/jblas/TestBlasDoubleComplex.java
similarity index 92%
rename from test/org/jblas/la/TestBlasDoubleComplex.java
rename to test/org/jblas/TestBlasDoubleComplex.java
index d3371ed..75744f9 100644
--- a/test/org/jblas/la/TestBlasDoubleComplex.java
+++ b/test/org/jblas/TestBlasDoubleComplex.java
@@ -34,18 +34,18 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 import junit.framework.TestCase;
 
-import org.jblas.core.ComplexDouble;
+import org.jblas.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);
+		ComplexDouble c = NativeBlas.zdotu(3, a, 0, 1, a, 0, 1);
 		System.out.println(c);
 	}
 
@@ -54,10 +54,10 @@ public class TestBlasDoubleComplex extends TestCase {
 		double[] y = new double[] { 0.0, 1.0 };
 		ComplexDouble a = new ComplexDouble(0.0, 1.0);
 		
-		Blas.zdscal(1, 2.0, x, 0, 1);
+		NativeBlas.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);
+		NativeBlas.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/TestBlasFloat.java
similarity index 88%
rename from test/org/jblas/la/TestBlasFloat.java
rename to test/org/jblas/TestBlasFloat.java
index 5a60944..89224f7 100644
--- a/test/org/jblas/la/TestBlasFloat.java
+++ b/test/org/jblas/TestBlasFloat.java
@@ -34,11 +34,11 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 import junit.framework.TestCase;
 
-import static org.jblas.la.MatrixFunctions.*;
+import static org.jblas.MatrixFunctions.*;
 
 public class TestBlasFloat extends TestCase {
 
@@ -46,9 +46,9 @@ public class TestBlasFloat extends TestCase {
 	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));
+		assertEquals(10.0f, NativeBlas.sasum(4, a, 0, 1));
+		assertEquals(4.0f, NativeBlas.sasum(2, a, 0, 2));
+		assertEquals(5.0f, NativeBlas.sasum(2, a, 1, 1));
 	}
 	
 	/** test scalar product */
@@ -56,9 +56,9 @@ public class TestBlasFloat extends TestCase {
 		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));
+		assertEquals(32.0f, NativeBlas.sdot(3, a, 0, 1, b, 0, 1));
+		assertEquals(22.0f, NativeBlas.sdot(2, a, 0, 2, b, 0, 2));
+		assertEquals(5.0f + 12.0f + 21.0f, NativeBlas.sdot(3, a, 0, 1, b, 1, 1));
 	}
 	
         public void testSwap() {
@@ -68,12 +68,12 @@ public class TestBlasFloat extends TestCase {
             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);
+            NativeBlas.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);
+            NativeBlas.sswap(2, a, 0, 2, a, 1, 2);
             assertTrue(arraysEqual(a, 5.0f, 4.0f, 7.0f, 6.0f));
         }
         
@@ -82,7 +82,7 @@ public class TestBlasFloat extends TestCase {
 		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);
+		NativeBlas.saxpy(4, 2.0f, x, 0, 1, y, 0, 1);
 		
 		for(int i = 0; i < 4; i++)
 			assertEquals(2*x[i], y[i]);
@@ -97,7 +97,7 @@ public class TestBlasFloat extends TestCase {
 		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);
+		NativeBlas.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);
@@ -105,7 +105,7 @@ public class TestBlasFloat extends TestCase {
 		
 		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);
+		NativeBlas.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));
diff --git a/test/org/jblas/core/TestComplexFloat.java b/test/org/jblas/TestComplexFloat.java
similarity index 97%
rename from test/org/jblas/core/TestComplexFloat.java
rename to test/org/jblas/TestComplexFloat.java
index cc19d09..bbbc5f5 100644
--- a/test/org/jblas/core/TestComplexFloat.java
+++ b/test/org/jblas/TestComplexFloat.java
@@ -34,9 +34,8 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.core;
+package org.jblas;
 
-import org.jblas.core.ComplexFloat;
 import junit.framework.TestCase;
 
 public class TestComplexFloat extends TestCase {
diff --git a/test/org/jblas/la/TestDoubleMatrix.java b/test/org/jblas/TestDoubleMatrix.java
similarity index 94%
rename from test/org/jblas/la/TestDoubleMatrix.java
rename to test/org/jblas/TestDoubleMatrix.java
index 66397d3..b3f5a49 100644
--- a/test/org/jblas/la/TestDoubleMatrix.java
+++ b/test/org/jblas/TestDoubleMatrix.java
@@ -34,14 +34,13 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.DoubleMatrix;
-import org.jblas.la.Geometry;
-import org.jblas.la.Solve;
+import java.io.File;
+import java.io.PrintStream;
 import junit.framework.TestCase;
 import java.util.Arrays;
-import static org.jblas.la.ranges.RangeUtils.*;
+import static org.jblas.ranges.RangeUtils.*;
 
 public class TestDoubleMatrix extends TestCase {
 
@@ -537,7 +536,6 @@ public class TestDoubleMatrix extends TestCase {
     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);
     }
@@ -550,16 +548,16 @@ public class TestDoubleMatrix extends TestCase {
     }
 
     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 AA = new DoubleMatrix(3, 3, 3.0, 5.0, 6.0, 1.0, 0.0, 0.0, 2.0, 4.0, 0.0);
+        DoubleMatrix BB = new DoubleMatrix(3, 1, 1.0, 2.0, 3.0);
 
-        DoubleMatrix Adup = A.dup();
-        DoubleMatrix Bdup = B.dup();
+        DoubleMatrix Adup = AA.dup();
+        DoubleMatrix Bdup = BB.dup();
 
-        DoubleMatrix X = Solve.solve(A, B);
+        DoubleMatrix X = Solve.solve(AA, BB);
 
-        assertEquals(Adup, A);
-        assertEquals(Bdup, B);
+        assertEquals(Adup, AA);
+        assertEquals(Bdup, BB);
     }
 
     public void testConstructFromArray() {
@@ -627,15 +625,23 @@ public class TestDoubleMatrix extends TestCase {
 
     public void testLoadAsciiFile() {
         try {
-            DoubleMatrix result = DoubleMatrix.loadAsciiFile("/home/mikio/datasets/banana/banana_train_data_1.asc");
-            result.print();
+            File f = File.createTempFile("jblas-test", "txt");
+            f.deleteOnExit();
+            PrintStream out = new PrintStream(f);
+            out.println("1.0 2.0 3.0");
+            out.println("4.0 5.0 6.0");
+            out.close();
+
+            DoubleMatrix result = DoubleMatrix.loadAsciiFile(f.getAbsolutePath());
+            assertEquals(new DoubleMatrix(2, 3, 1.0, 4.0, 2.0, 5.0, 3.0, 6.0), result);
         } catch (Exception e) {
             fail("Caught exception " + e);
         }
     }
     
     public void testRanges() {
-        A.print();
-        A.get(interval(0, 2), interval(0, 1)).print();
+        // Hm... Broken?
+        //System.out.printf("Ranges: %s\n", A.get(interval(0, 2), interval(0, 1)).toString());
+        //assertEquals(new DoubleMatrix(3, 2, 1.0, 2.0, 3.0, 5.0, 6.0, 7.0), );
     }
 }
diff --git a/test/org/jblas/la/EigenTest.java b/test/org/jblas/TestEigen.java
similarity index 75%
rename from test/org/jblas/la/EigenTest.java
rename to test/org/jblas/TestEigen.java
index 446af1a..7bb425b 100644
--- a/test/org/jblas/la/EigenTest.java
+++ b/test/org/jblas/TestEigen.java
@@ -38,21 +38,17 @@
  * To change this template, choose Tools | Templates
  * and open the template in the editor.
  */
-package org.jblas.la;
+package org.jblas;
 
-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 class TestEigen extends TestCase {
 
-    public EigenTest(String testName) {
+    public TestEigen(String testName) {
         super(testName);
     }
 
@@ -61,19 +57,11 @@ public class EigenTest extends TestCase {
 
         ComplexDoubleMatrix E = Eigen.eigenvalues(A);
         
-        System.out.printf("E = %s\n", E.toString());
+        //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());
+        //System.out.printf("values = %s\n", EV[1].toString());
+        //System.out.printf("vectors = %s\n", EV[0].toString());
     }
 }
diff --git a/test/org/jblas/la/TestFloatMatrix.java b/test/org/jblas/TestFloatMatrix.java
similarity index 94%
rename from test/org/jblas/la/TestFloatMatrix.java
rename to test/org/jblas/TestFloatMatrix.java
index 9b3b737..c669188 100644
--- a/test/org/jblas/la/TestFloatMatrix.java
+++ b/test/org/jblas/TestFloatMatrix.java
@@ -34,14 +34,13 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.FloatMatrix;
-import org.jblas.la.Geometry;
-import org.jblas.la.Solve;
+import java.io.File;
+import java.io.PrintStream;
 import junit.framework.TestCase;
 import java.util.Arrays;
-import static org.jblas.la.ranges.RangeUtils.*;
+import static org.jblas.ranges.RangeUtils.*;
 
 public class TestFloatMatrix extends TestCase {
 
@@ -537,7 +536,6 @@ public class TestFloatMatrix extends TestCase {
     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);
     }
@@ -550,16 +548,16 @@ public class TestFloatMatrix extends TestCase {
     }
 
     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 AA = new FloatMatrix(3, 3, 3.0f, 5.0f, 6.0f, 1.0f, 0.0f, 0.0f, 2.0f, 4.0f, 0.0f);
+        FloatMatrix BB = new FloatMatrix(3, 1, 1.0f, 2.0f, 3.0f);
 
-        FloatMatrix Adup = A.dup();
-        FloatMatrix Bdup = B.dup();
+        FloatMatrix Adup = AA.dup();
+        FloatMatrix Bdup = BB.dup();
 
-        FloatMatrix X = Solve.solve(A, B);
+        FloatMatrix X = Solve.solve(AA, BB);
 
-        assertEquals(Adup, A);
-        assertEquals(Bdup, B);
+        assertEquals(Adup, AA);
+        assertEquals(Bdup, BB);
     }
 
     public void testConstructFromArray() {
@@ -627,15 +625,23 @@ public class TestFloatMatrix extends TestCase {
 
     public void testLoadAsciiFile() {
         try {
-            FloatMatrix result = FloatMatrix.loadAsciiFile("/home/mikio/datasets/banana/banana_train_data_1.asc");
-            result.print();
+            File f = File.createTempFile("jblas-test", "txt");
+            f.deleteOnExit();
+            PrintStream out = new PrintStream(f);
+            out.println("1.0f 2.0f 3.0f");
+            out.println("4.0f 5.0f 6.0f");
+            out.close();
+
+            FloatMatrix result = FloatMatrix.loadAsciiFile(f.getAbsolutePath());
+            assertEquals(new FloatMatrix(2, 3, 1.0f, 4.0f, 2.0f, 5.0f, 3.0f, 6.0f), result);
         } catch (Exception e) {
             fail("Caught exception " + e);
         }
     }
     
     public void testRanges() {
-        A.print();
-        A.get(interval(0, 2), interval(0, 1)).print();
+        // Hm... Broken?
+        //System.out.printf("Ranges: %s\n", A.get(interval(0, 2), interval(0, 1)).toString());
+        //assertEquals(new FloatMatrix(3, 2, 1.0f, 2.0f, 3.0f, 5.0f, 6.0f, 7.0f), );
     }
 }
diff --git a/test/org/jblas/la/TestGeometry.java b/test/org/jblas/TestGeometry.java
similarity index 97%
rename from test/org/jblas/la/TestGeometry.java
rename to test/org/jblas/TestGeometry.java
index 70efc93..557b590 100644
--- a/test/org/jblas/la/TestGeometry.java
+++ b/test/org/jblas/TestGeometry.java
@@ -34,10 +34,8 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.DoubleMatrix;
-import org.jblas.la.Geometry;
 import junit.framework.TestCase;
 
 public class TestGeometry extends TestCase {
diff --git a/test/org/jblas/la/TestMatrixFunctions.java b/test/org/jblas/TestMatrixFunctions.java
similarity index 95%
rename from test/org/jblas/la/TestMatrixFunctions.java
rename to test/org/jblas/TestMatrixFunctions.java
index 1ab992a..a772ebb 100644
--- a/test/org/jblas/la/TestMatrixFunctions.java
+++ b/test/org/jblas/TestMatrixFunctions.java
@@ -34,11 +34,10 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
-import org.jblas.la.DoubleMatrix;
 import junit.framework.TestCase;
-import static org.jblas.la.MatrixFunctions.*;
+import static org.jblas.MatrixFunctions.*;
 
 public class TestMatrixFunctions extends TestCase {
 	public void testAbs() {
diff --git a/test/org/jblas/la/TestSolve.java b/test/org/jblas/TestSolve.java
similarity index 97%
rename from test/org/jblas/la/TestSolve.java
rename to test/org/jblas/TestSolve.java
index 8c535e8..1cd7f79 100644
--- a/test/org/jblas/la/TestSolve.java
+++ b/test/org/jblas/TestSolve.java
@@ -34,12 +34,10 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 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);
diff --git a/test/org/jblas/la/TicToc.java b/test/org/jblas/TicToc.java
similarity index 99%
rename from test/org/jblas/la/TicToc.java
rename to test/org/jblas/TicToc.java
index 4de4789..6b5049a 100644
--- a/test/org/jblas/la/TicToc.java
+++ b/test/org/jblas/TicToc.java
@@ -34,7 +34,7 @@
  */
 // --- END LICENSE BLOCK ---
 
-package org.jblas.la;
+package org.jblas;
 
 public class TicToc {
     private static long savedTime;

-- 
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